From a5919dc7677700b0e7462a7a4ed3f21655822f19 Mon Sep 17 00:00:00 2001 From: Rohil Surana Date: Tue, 31 Mar 2015 02:57:52 +0530 Subject: [PATCH 01/51] Typing indicator shows up once typing is resumed --- src/widget/form/chatform.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 48208c808..ae3fbe8d0 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -89,7 +89,10 @@ ChatForm::ChatForm(Friend* chatFriend) connect(volButton, SIGNAL(clicked()), this, SLOT(onVolMuteToggle())); connect(Core::getInstance(), &Core::fileSendFailed, this, &ChatForm::onFileSendFailed); connect(this, SIGNAL(chatAreaCleared()), getOfflineMsgEngine(), SLOT(removeAllReciepts())); - connect(&typingTimer, &QTimer::timeout, this, [=]{Core::getInstance()->sendTyping(f->getFriendID(), false);}); + connect(&typingTimer, &QTimer::timeout, this, [=]{ + Core::getInstance()->sendTyping(f->getFriendID(), false); + isTyping = false; + } ); connect(nameLabel, &CroppingLabel::textChanged, this, [=](QString text, QString orig) { if (text != orig) emit aliasChanged(text); } ); From 394ebaced8781e852fc0565217c45e3f84c2f1c5 Mon Sep 17 00:00:00 2001 From: Ansa89 Date: Fri, 3 Apr 2015 13:20:02 +0200 Subject: [PATCH 02/51] Italian translation: update --- translations/it.ts | 152 +++++++++++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 68 deletions(-) diff --git a/translations/it.ts b/translations/it.ts index 83b6e6710..f621a499a 100644 --- a/translations/it.ts +++ b/translations/it.ts @@ -116,62 +116,62 @@ qualità video elevate, questo può causare problemi con le chiamate video. AddFriendForm - + Add Friends Aggiungi Contatto - + Tox ID Tox ID of the person you're sending a friend request to Tox ID - + Message The message you send in friend requests Messaggio - + Send friend request Invia richiesta d'amicizia - + %1 here! Tox me maybe? Default message in friend requests if the field is left blank. Write something appropriate! Ciao, sono %1. Permettimi di aggiungerti alla mia lista contatti. - + Please fill in a valid Tox ID Tox ID of the friend you're sending a friend request to Inserisci un Tox ID valido - - + + Couldn't add friend Impossibile aggiungere il contatto - + You can't add yourself as a friend! When trying to add your own Tox ID as friend Non puoi aggiungere te stesso come contatto! - + qTox needs to use the Tox DNS, but can't do it through a proxy. Ignore the proxy and connect to the Internet directly? qTox deve usare Tox DNS, ma non può farlo attraverso un proxy. Ignorare le impostazioni del proxy e connettersi direttamente alla rete Tox? - + This Tox ID does not exist DNS error Questo Tox ID non esiste @@ -413,12 +413,12 @@ Ignorare le impostazioni del proxy e connettersi direttamente alla rete Tox?Invio del file "%1" fallito - + Call with %1 ended. %2 Chiamata con %1 terminata. %2 - + Call duration: Durata chiamata: @@ -760,30 +760,30 @@ Soprannome: GeneralForm - + General Generale - - + + None Nessuno - + Choose an auto accept directory popup title Scegli dove salvare i files accettati automaticamente - + Call active popup title Chiamata in corso - + You can't disconnect while a call is active! popup text Non puoi disconnetterti mentre c'è una chiamata in corso! @@ -929,62 +929,55 @@ nella traybar invece che nella taskbar. Play sound Riproduci suono - - - Messages you are trying to send to your friends when they are not online -will be sent to them when they will appear online to you. - toolTip for Faux offline messaging setting - I messaggi che invii ai contatti offline saranno inviati quando appaiono online. - Compact contact list Usa lista contatti compatta - + Smiley Pack: Text on smiley pack label Emoticons: - + Emoticon size: Dimensione: - + Style: Stile: - + Theme color: Colore tema: - + Timestamp format: Formato data/ora: - + Connection Settings Impostazioni Connessione - + Enable IPv6 (recommended) Text on a checkbox to enable IPv6 Abilita IPv6 (consigliato) - + Proxy type: Proxy: - + Address: Text on proxy addr label Indirizzo: @@ -1046,6 +1039,13 @@ will be sent to them when they will appear online to you. toolTip for Focus window setting Dai il focus alla finestra di qTox quando arriva un nuovo messaggio. + + + Messages you are trying to send to your friends when they are not online +will be sent to them when they appear online to you. + toolTip for Faux offline messaging setting + I messaggi che invii ai contatti offline, saranno spediti quando appaiono online. + Your contact list will be shown in compact mode. @@ -1053,55 +1053,71 @@ will be sent to them when they will appear online to you. La lista contatti sarà visualizzata in modo compatto. - + + If checked, groupchats will be placed at the top of the friends list, otherwise, they'll be placed below online friends. + toolTip for groupchat positioning + Le chat di gruppo saranno posizionate all'inizio della lista contatti, altrimenti saranno posizionate sotto ai contatti online. + + + + Place groupchats at top of friend list + Posiziona le chat di gruppo in cima alla lista contatti + + + Theme Impostazioni Tema - + Use emoticons Usa emoticons - + px px - + + Date format: + Formato data: + + + Disabling this allows, e.g., toxing over Tor. It adds load to the Tox network however, so uncheck only when necessary. force tcp checkbox tooltip Disabilitando questo sarà possibile usare qTox con Tor. Tuttavia verrà aggiunto carico alla rete Tox, quindi disabilitare solo se necessario. - + Enable UDP (recommended) Text on checkbox to disable UDP Abilita UDP (consigliato) - + None Nessuno - + SOCKS5 SOCKS 5 - + HTTP HTTP - + Port Text on proxy port label Porta - + Reconnect reconnect button Riconnetti @@ -2084,131 +2100,131 @@ Se non sei sicuro, scegli "No", così le informazioni inviate al serve Widget - + &Quit &Esci - + Online Button to set your status to 'Online' Online - + Away Button to set your status to 'Away' Assente - + Busy Button to set your status to 'Busy' Occupato - + Toxcore failed to start, the application will terminate after you close this message. Impossibile avviare Toxcore.\nqTox terminerà dopo che avrai chiuso questo messaggio. - + toxcore failed to start with your proxy settings. qTox cannot run; please modify your settings and restart. popup text Impossibile avviare Toxcore con le tue impostazione proxy.\nqTox non può funzionare correttamente, per favore modifica le impostazioni e riavvia il programma. - + Add friend Aggiungi contatto - + File transfers Files trasferiti - + Executable file popup title File eseguibile - + 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? - + Settings Impostazioni - + Profile Profilo - + Couldn't request friendship Impossibile inviare la richiesta d'amicizia - + away contact status assente - + busy contact status occupato - + offline contact status offline - + online contact status online - + %1 is now %2 e.g. "Dubslow is now online" %1 è ora %2 - + Group invite popup title Invito chat di gruppo - + %1 has invited you to a groupchat. Would you like to join? popup text %1 ti ha invitato in una chat di gruppo. Vuoi partecipare? - + <Unknown> Placeholder when we don't know someone's name in a group chat <Sconosciuto> - + %1 has set the title to %2 %1 ha impostato il titolo in %2 - + Message failed to send Impossibile inviare il messaggio From fb97662b5dc99d804031df00ecd8f0f80b3159e4 Mon Sep 17 00:00:00 2001 From: Rohil Surana Date: Sat, 4 Apr 2015 23:52:48 +0530 Subject: [PATCH 03/51] Added add friend on window on first start --- src/widget/widget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index fdb4e5591..b9d5bd2ea 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -197,6 +197,7 @@ void Widget::init() connect(offlineMsgTimer, &QTimer::timeout, this, &Widget::processOfflineMsgs); addFriendForm->show(*ui); + setWindowTitle(tr("Add friend")); connect(settingsWidget, &SettingsWidget::groupchatPositionToggled, contactListWidget, &FriendListWidget::onGroupchatPositionChanged); #if (AUTOUPDATE_ENABLED) From 55d33fbcc000b4b29151e63b614b66e2014cc0ac Mon Sep 17 00:00:00 2001 From: PKEv Date: Mon, 13 Apr 2015 00:49:24 +0300 Subject: [PATCH 04/51] correct after CppCheck --- src/chatlog/chatline.cpp | 6 +++--- src/chatlog/chatline.h | 6 +++--- src/video/cameraworker.cpp | 12 +++++++----- src/widget/form/groupchatform.cpp | 3 +-- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/chatlog/chatline.cpp b/src/chatlog/chatline.cpp index d3617b347..271424a90 100644 --- a/src/chatlog/chatline.cpp +++ b/src/chatlog/chatline.cpp @@ -244,17 +244,17 @@ void ChatLine::moveBy(qreal deltaY) bbox.moveTop(bbox.top() + deltaY); } -bool ChatLine::lessThanBSRectTop(const ChatLine::Ptr lhs, const qreal rhs) +bool ChatLine::lessThanBSRectTop(const ChatLine::Ptr& lhs, const qreal& rhs) { return lhs->sceneBoundingRect().top() < rhs; } -bool ChatLine::lessThanBSRectBottom(const ChatLine::Ptr lhs, const qreal rhs) +bool ChatLine::lessThanBSRectBottom(const ChatLine::Ptr& lhs, const qreal& rhs) { return lhs->sceneBoundingRect().bottom() < rhs; } -bool ChatLine::lessThanRowIndex(const ChatLine::Ptr lhs, const ChatLine::Ptr rhs) +bool ChatLine::lessThanRowIndex(const ChatLine::Ptr& lhs, const ChatLine::Ptr& rhs) { return lhs->getRow() < rhs->getRow(); } diff --git a/src/chatlog/chatline.h b/src/chatlog/chatline.h index 0f7405cff..40b124227 100644 --- a/src/chatlog/chatline.h +++ b/src/chatlog/chatline.h @@ -82,9 +82,9 @@ public: bool isOverSelection(QPointF scenePos); //comparators - static bool lessThanBSRectTop(const ChatLine::Ptr lhs, const qreal rhs); - static bool lessThanBSRectBottom(const ChatLine::Ptr lhs, const qreal rhs); - static bool lessThanRowIndex(const ChatLine::Ptr lhs, const ChatLine::Ptr rhs); + static bool lessThanBSRectTop(const ChatLine::Ptr& lhs, const qreal& rhs); + static bool lessThanBSRectBottom(const ChatLine::Ptr& lhs, const qreal& rhs); + static bool lessThanRowIndex(const ChatLine::Ptr& lhs, const ChatLine::Ptr& rhs); protected: friend class ChatLog; diff --git a/src/video/cameraworker.cpp b/src/video/cameraworker.cpp index 47acb377a..e972ef58d 100644 --- a/src/video/cameraworker.cpp +++ b/src/video/cameraworker.cpp @@ -37,12 +37,14 @@ CameraWorker::~CameraWorker() void CameraWorker::onStart() { - clock = new QTimer(this); - clock->setSingleShot(false); - clock->setInterval(1000/60); - - connect(clock, &QTimer::timeout, this, &CameraWorker::doWork); + if (!clock) + { + clock = new QTimer(this); + clock->setSingleShot(false); + clock->setInterval(1000/60); + connect(clock, &QTimer::timeout, this, &CameraWorker::doWork); + } emit started(); } diff --git a/src/widget/form/groupchatform.cpp b/src/widget/form/groupchatform.cpp index fc4c6d499..c544432ec 100644 --- a/src/widget/form/groupchatform.cpp +++ b/src/widget/form/groupchatform.cpp @@ -64,11 +64,10 @@ GroupChatForm::GroupChatForm(Group* chatGroup) namesListLayout = new FlowLayout(0,5,0); QStringList names(group->getPeerList()); - QLabel *l; for (const QString& name : names) { - l = new QLabel(name); + QLabel *l = new QLabel(name); l->setTextFormat(Qt::PlainText); namesListLayout->addWidget(l); } From 228398d5de5c84f020e912c8fa27d32f3d77a225 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sun, 19 Apr 2015 23:12:44 +0200 Subject: [PATCH 05/51] Initial porting to the new Tox API Builds and runs, but some features will be missing, may crash with an assert, or silently fail with broken QObject connections We're back in the game. --- src/core.cpp | 448 ++++++++++++++++-------------- src/core.h | 132 ++++----- src/coreav.cpp | 42 +-- src/coreav.h | 4 +- src/coreencryption.cpp | 68 +++-- src/corestructs.cpp | 6 +- src/corestructs.h | 6 +- src/friend.cpp | 4 +- src/friend.h | 6 +- src/friendlist.h | 2 +- src/group.h | 2 +- src/misc/cdata.cpp | 2 +- src/misc/db/encrypteddb.cpp | 2 +- src/nexus.cpp | 5 +- src/offlinemsgengine.h | 2 +- src/toxdns.cpp | 8 +- src/widget/form/chatform.cpp | 34 +-- src/widget/form/chatform.h | 39 ++- src/widget/form/genericchatform.h | 4 +- src/widget/form/profileform.cpp | 17 +- src/widget/friendlistwidget.cpp | 2 +- src/widget/friendlistwidget.h | 2 +- src/widget/widget.cpp | 31 +-- src/widget/widget.h | 6 +- 24 files changed, 446 insertions(+), 428 deletions(-) diff --git a/src/core.cpp b/src/core.cpp index b407ee2f3..2269039e1 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -133,7 +134,7 @@ Core* Core::getInstance() return Nexus::getCore(); } -void Core::make_tox() +void Core::make_tox(QByteArray savedata) { // IPv6 needed for LAN discovery, but can crash some weird routers. On by default, can be disabled in options. bool enableIPv6 = Settings::getInstance().getEnableIPv6(); @@ -146,12 +147,12 @@ void Core::make_tox() qWarning() << "Core starting with IPv6 disabled. LAN discovery may not work properly."; Tox_Options toxOptions; - toxOptions.ipv6enabled = enableIPv6; - toxOptions.udp_disabled = forceTCP; + toxOptions.ipv6_enabled = enableIPv6; + toxOptions.udp_enabled = !forceTCP; // No proxy by default - toxOptions.proxy_type = TOX_PROXY_NONE; - toxOptions.proxy_address[0] = 0; + toxOptions.proxy_type = TOX_PROXY_TYPE_NONE; + toxOptions.proxy_host = nullptr; toxOptions.proxy_port = 0; if (proxyType != ProxyType::ptNone) @@ -168,25 +169,28 @@ void Core::make_tox() qDebug() << "Core: using proxy" << proxyAddr << ":" << proxyPort; // protection against changings in TOX_PROXY_TYPE enum if (proxyType == ProxyType::ptSOCKS5) - toxOptions.proxy_type = TOX_PROXY_SOCKS5; + toxOptions.proxy_type = TOX_PROXY_TYPE_SOCKS5; else if (proxyType == ProxyType::ptHTTP) - toxOptions.proxy_type = TOX_PROXY_HTTP; - uint16_t sz = CString::fromString(proxyAddr, (unsigned char*)toxOptions.proxy_address); - toxOptions.proxy_address[sz] = 0; + 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_port = proxyPort; } } - tox = tox_new(&toxOptions); + tox = tox_new(&toxOptions, (uint8_t*)savedata.data(), savedata.size(), nullptr); if (tox == nullptr) { if (enableIPv6) // Fallback to IPv4 { - toxOptions.ipv6enabled = false; - tox = tox_new(&toxOptions); + toxOptions.ipv6_enabled = false; + tox = tox_new(&toxOptions, (uint8_t*)savedata.data(), savedata.size(), nullptr); if (tox == nullptr) { - if (toxOptions.proxy_type != TOX_PROXY_NONE) + if (toxOptions.proxy_type != TOX_PROXY_TYPE_NONE) { qCritical() << "Core: bad proxy! no toxcore!"; emit badProxy(); @@ -201,7 +205,7 @@ void Core::make_tox() else qWarning() << "Core failed to start with IPv6, falling back to IPv4. LAN discovery may not work properly."; } - else if (toxOptions.proxy_type != TOX_PROXY_NONE) + else if (toxOptions.proxy_type != TOX_PROXY_TYPE_NONE) { emit badProxy(); return; @@ -227,29 +231,33 @@ void Core::start() { qDebug() << "Core: Starting up"; - make_tox(); + QByteArray savedata = loadToxSave(loadPath); + + make_tox(savedata); qsrand(time(nullptr)); - if (loadPath != "") + /** TODO: Review this mess. Actually rewrite it all + * I have no idea what the whole fooling around with loadPath bussiness means anymore. + * Let's write something clear that doesn't rely on magic global state instead + * We need to: 1) Find a qTox profile, create if needed 2) Find a tox save, decrypt/create if needed + * Not sure about the order tho. Look into this. + if (true) { - while (!loadConfiguration(loadPath)) + if (loadPath.isEmpty()) { - if (loadPath.isEmpty()) + QString profile; + if ((profile = loadOldInformation()).isEmpty()) { - QString profile; - if ((profile = loadOldInformation()).isEmpty()) - { - qCritical() << "Core: loadConfiguration failed, exiting now"; - emit failedToStart(); - return; - } - else - { - loadPath = QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT); - Settings::getInstance().switchProfile(profile); - HistoryKeeper::resetInstance(); // I'm not actually sure if this is necessary - } + qCritical() << "Core: loadConfiguration failed, exiting now"; + emit failedToStart(); + return; + } + else + { + loadPath = QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT); + Settings::getInstance().switchProfile(profile); + HistoryKeeper::resetInstance(); // I'm not actually sure if this is necessary } } // loadPath is meaningless after this @@ -263,26 +271,45 @@ void Core::start() setStatusMessage(tr("Toxing on qTox")); // this also solves the not updating issue setUsername(tr("qTox User")); } + */ + + // set GUI with user and statusmsg + QString name = getUsername(); + if (!name.isEmpty()) + emit usernameSet(name); + + QString msg = getStatusMessage(); + if (!msg.isEmpty()) + emit statusMessageSet(msg); + + QString id = getSelfId().toString(); + if (!id.isEmpty()) + emit idSet(id); + + // tox core is already decrypted + if (Settings::getInstance().getEnableLogging() && Settings::getInstance().getEncryptLogs()) + checkEncryptedHistory(); + + loadFriends(); tox_callback_friend_request(tox, onFriendRequest, this); tox_callback_friend_message(tox, onFriendMessage, this); - tox_callback_friend_action(tox, onAction, this); - tox_callback_name_change(tox, onFriendNameChange, this); - tox_callback_typing_change(tox, onFriendTypingChange, this); - tox_callback_status_message(tox, onStatusMessageChanged, this); - tox_callback_user_status(tox, onUserStatusChanged, this); - tox_callback_connection_status(tox, onConnectionStatusChanged, this); + tox_callback_friend_name(tox, onFriendNameChange, this); + tox_callback_friend_typing(tox, onFriendTypingChange, this); + tox_callback_friend_status_message(tox, onStatusMessageChanged, this); + tox_callback_friend_status(tox, onUserStatusChanged, this); + tox_callback_friend_connection_status(tox, onConnectionStatusChanged, this); tox_callback_group_invite(tox, onGroupInvite, this); tox_callback_group_message(tox, onGroupMessage, this); tox_callback_group_namelist_change(tox, onGroupNamelistChange, this); tox_callback_group_title(tox, onGroupTitleChange, this); tox_callback_group_action(tox, onGroupAction, this); - tox_callback_file_send_request(tox, onFileSendRequestCallback, this); - tox_callback_file_control(tox, onFileControlCallback, this); - tox_callback_file_data(tox, onFileDataCallback, this); - tox_callback_avatar_info(tox, onAvatarInfoCallback, this); - tox_callback_avatar_data(tox, onAvatarDataCallback, this); - tox_callback_read_receipt(tox, onReadReceiptCallback, this); + //tox_callback_file_send_request(tox, onFileSendRequestCallback, this); + //tox_callback_file_control(tox, onFileControlCallback, this); + //tox_callback_file_data(tox, onFileDataCallback, this); + //tox_callback_avatar_info(tox, onAvatarInfoCallback, this); + //tox_callback_avatar_data(tox, onAvatarDataCallback, this); + tox_callback_friend_read_receipt(tox, onReadReceiptCallback, this); toxav_register_callstate_callback(toxav, onAvInvite, av_OnInvite, this); toxav_register_callstate_callback(toxav, onAvStart, av_OnStart, this); @@ -306,7 +333,7 @@ void Core::start() buffer.open(QIODevice::WriteOnly); pic.save(&buffer, "PNG"); buffer.close(); - setAvatar(TOX_AVATAR_FORMAT_PNG, data); + setAvatar(data); } else qDebug() << "Core: Error loading self avatar"; @@ -331,7 +358,7 @@ void Core::process() return; static int tolerance = CORE_DISCONNECT_TOLERANCE; - tox_do(tox); + tox_iterate(tox); toxav_do(toxav); #ifdef DEBUG @@ -347,14 +374,14 @@ void Core::process() tolerance = 3*CORE_DISCONNECT_TOLERANCE; } - toxTimer->start(qMin(tox_do_interval(tox), toxav_do_interval(toxav))); + toxTimer->start(qMin(tox_iteration_interval(tox), toxav_do_interval(toxav))); } bool Core::checkConnection() { static bool isConnected = false; //static int count = 0; - bool toxConnected = tox_isconnected(tox); + bool toxConnected = tox_self_get_connection_status(tox) != TOX_CONNECTION_NONE; if (toxConnected && !isConnected) { qDebug() << "Core: Connected to DHT"; @@ -390,8 +417,8 @@ void Core::bootstrapDht() while (i < 2) // i think the more we bootstrap, the more we jitter because the more we overwrite nodes { const Settings::DhtServer& dhtServer = dhtServerList[j % listSize]; - if (tox_bootstrap_from_address(tox, dhtServer.address.toLatin1().data(), - dhtServer.port, CUserId(dhtServer.userId).data()) == 1) + if (tox_bootstrap(tox, dhtServer.address.toLatin1().data(), + dhtServer.port, CUserId(dhtServer.userId).data(), nullptr) == 1) qDebug() << QString("Core: Bootstrapping from ")+dhtServer.name+QString(", addr ")+dhtServer.address.toLatin1().data() +QString(", port ")+QString().setNum(dhtServer.port); else @@ -402,42 +429,47 @@ void Core::bootstrapDht() } } -void Core::onFriendRequest(Tox*/* tox*/, const uint8_t* cUserId, const uint8_t* cMessage, uint16_t cMessageSize, void* core) +void Core::onFriendRequest(Tox*/* tox*/, const uint8_t* cUserId, + const uint8_t* cMessage, size_t cMessageSize, void* core) { - emit static_cast(core)->friendRequestReceived(CUserId::toString(cUserId), CString::toString(cMessage, cMessageSize)); + emit static_cast(core)->friendRequestReceived(CUserId::toString(cUserId), + CString::toString(cMessage, cMessageSize)); } -void Core::onFriendMessage(Tox*/* tox*/, int friendId, const uint8_t* cMessage, uint16_t cMessageSize, void* core) +void Core::onFriendMessage(Tox*/* tox*/, uint32_t friendId, TOX_MESSAGE_TYPE type, + const uint8_t* cMessage, size_t cMessageSize, void* core) { - emit static_cast(core)->friendMessageReceived(friendId, CString::toString(cMessage, cMessageSize), false); + emit static_cast(core)->friendMessageReceived(friendId,CString::toString(cMessage, cMessageSize), false); } -void Core::onFriendNameChange(Tox*/* tox*/, int friendId, const uint8_t* cName, uint16_t cNameSize, void* core) +void Core::onFriendNameChange(Tox*/* tox*/, uint32_t friendId, + const uint8_t* cName, size_t cNameSize, void* core) { emit static_cast(core)->friendUsernameChanged(friendId, CString::toString(cName, cNameSize)); } -void Core::onFriendTypingChange(Tox*/* tox*/, int friendId, uint8_t isTyping, void *core) +void Core::onFriendTypingChange(Tox*/* tox*/, uint32_t friendId, bool isTyping, void *core) { emit static_cast(core)->friendTypingChanged(friendId, isTyping ? true : false); } -void Core::onStatusMessageChanged(Tox*/* tox*/, int friendId, const uint8_t* cMessage, uint16_t cMessageSize, void* core) +void Core::onStatusMessageChanged(Tox*/* tox*/, uint32_t friendId, const uint8_t* cMessage, + size_t cMessageSize, void* core) { emit static_cast(core)->friendStatusMessageChanged(friendId, CString::toString(cMessage, cMessageSize)); } -void Core::onUserStatusChanged(Tox*/* tox*/, int friendId, uint8_t userstatus, void* core) +void Core::onUserStatusChanged(Tox*/* tox*/, uint32_t friendId, TOX_USER_STATUS userstatus, void* core) { Status status; switch (userstatus) { - case TOX_USERSTATUS_NONE: + case TOX_USER_STATUS_NONE: status = Status::Online; break; - case TOX_USERSTATUS_AWAY: + case TOX_USER_STATUS_AWAY: status = Status::Away; break; - case TOX_USERSTATUS_BUSY: + case TOX_USER_STATUS_BUSY: status = Status::Busy; break; default: @@ -445,13 +477,10 @@ void Core::onUserStatusChanged(Tox*/* tox*/, int friendId, uint8_t userstatus, v break; } - if (status == Status::Online || status == Status::Away) - tox_request_avatar_info(static_cast(core)->tox, friendId); - emit static_cast(core)->friendStatusChanged(friendId, status); } -void Core::onConnectionStatusChanged(Tox*/* tox*/, int friendId, uint8_t status, void* core) +void Core::onConnectionStatusChanged(Tox*/* tox*/, uint32_t friendId, TOX_CONNECTION status, void* core) { Status friendStatus = status ? Status::Online : Status::Offline; emit static_cast(core)->friendStatusChanged(friendId, friendStatus); @@ -480,36 +509,31 @@ void Core::onConnectionStatusChanged(Tox*/* tox*/, int friendId, uint8_t status, if (f.friendId == friendId && f.status == ToxFile::BROKEN) { qDebug() << QString("Core::onConnectionStatusChanged: %1: resuming broken filetransfer from position: %2").arg(f.file->fileName()).arg(f.bytesSent); - tox_file_send_control(static_cast(core)->tox, friendId, 1, f.fileNum, TOX_FILECONTROL_RESUME_BROKEN, reinterpret_cast(&f.bytesSent), sizeof(uint64_t)); + tox_file_control(static_cast(core)->tox, friendId, f.fileNum, TOX_FILE_CONTROL_RESUME, nullptr); emit static_cast(core)->fileTransferBrokenUnbroken(f, false); } } } } -void Core::onAction(Tox*/* tox*/, int friendId, const uint8_t *cMessage, uint16_t cMessageSize, void *core) -{ - emit static_cast(core)->friendMessageReceived(friendId, CString::toString(cMessage, cMessageSize), true); -} - void Core::onGroupAction(Tox*, int groupnumber, int peernumber, const uint8_t *action, uint16_t length, void* _core) { Core* core = static_cast(_core); emit core->groupMessageReceived(groupnumber, peernumber, CString::toString(action, length), true); } -void Core::onGroupInvite(Tox*, int friendnumber, uint8_t type, const uint8_t *data, uint16_t length,void *core) +void Core::onGroupInvite(Tox*, int32_t friendNumber, uint8_t type, const uint8_t *data, uint16_t length,void *core) { QByteArray pk((char*)data, length); if (type == TOX_GROUPCHAT_TYPE_TEXT) { - qDebug() << QString("Core: Text group invite by %1").arg(friendnumber); - emit static_cast(core)->groupInviteReceived(friendnumber,type,pk); + qDebug() << QString("Core: Text group invite by %1").arg(friendNumber); + emit static_cast(core)->groupInviteReceived(friendNumber,type,pk); } else if (type == TOX_GROUPCHAT_TYPE_AV) { - qDebug() << QString("Core: AV group invite by %1").arg(friendnumber); - emit static_cast(core)->groupInviteReceived(friendnumber,type,pk); + qDebug() << QString("Core: AV group invite by %1").arg(friendNumber); + emit static_cast(core)->groupInviteReceived(friendNumber,type,pk); } else { @@ -539,7 +563,7 @@ void Core::onGroupTitleChange(Tox*, int groupnumber, int peernumber, const uint8 emit core->groupTitleChanged(groupnumber, author, CString::toString(title, len)); } -void Core::onFileSendRequestCallback(Tox*, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, +void Core::onFileSendRequestCallback(Tox*, uint32_t friendnumber, uint8_t filenumber, uint64_t filesize, const uint8_t *filename, uint16_t filename_length, void *core) { qDebug() << QString("Core: Received file request %1 with friend %2").arg(filenumber).arg(friendnumber); @@ -550,7 +574,7 @@ void Core::onFileSendRequestCallback(Tox*, int32_t friendnumber, uint8_t filenum fileRecvQueue.append(file); emit static_cast(core)->fileReceiveRequested(fileRecvQueue.last()); } -void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, +void Core::onFileControlCallback(Tox* tox, uint32_t friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type, const uint8_t* data, uint16_t length, void *core) { ToxFile* file{nullptr}; @@ -581,7 +605,7 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive qWarning("Core::onFileControlCallback: No such file in queue"); return; } - if (receive_send == 1 && control_type == TOX_FILECONTROL_ACCEPT) + if (receive_send == 1 && control_type == TOX_FILE_CONTROL_RESUME) { file->status = ToxFile::TRANSMITTING; emit static_cast(core)->fileTransferAccepted(*file); @@ -591,7 +615,7 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive file->sendTimer->setSingleShot(true); file->sendTimer->start(TOX_FILE_INTERVAL); } - else if (receive_send == 1 && control_type == TOX_FILECONTROL_KILL) + else if (receive_send == 1 && control_type == TOX_FILE_CONTROL_CANCEL) { qDebug() << QString("Core::onFileControlCallback: Transfer of file %1 cancelled by friend %2") .arg(file->fileNum).arg(file->friendId); @@ -610,7 +634,7 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive } removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); } - else if (receive_send == 1 && control_type == TOX_FILECONTROL_FINISHED) + else if (receive_send == 1 && false /* && control_type == TOX_FILECONTROL_FINISHED*/ ) ///TODO: FIXME: Detect finished transfers { qDebug() << QString("Core::onFileControlCallback: Transfer of file %1 to friend %2 is complete") .arg(file->fileNum).arg(file->friendId); @@ -618,7 +642,7 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive emit static_cast(core)->fileTransferFinished(*file); removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); } - else if (receive_send == 0 && control_type == TOX_FILECONTROL_KILL) + else if (receive_send == 0 && control_type == TOX_FILE_CONTROL_CANCEL) { qDebug() << QString("Core::onFileControlCallback: Transfer of file %1 cancelled by friend %2") .arg(file->fileNum).arg(file->friendId); @@ -626,17 +650,17 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive emit static_cast(core)->fileTransferCancelled(*file); removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); } - else if (receive_send == 0 && control_type == TOX_FILECONTROL_FINISHED) + else if (receive_send == 0 && false /* && control_type == TOX_FILECONTROL_FINISHED*/ ) ///TODO: FIXME: Detect finished transfers { qDebug() << QString("Core::onFileControlCallback: Reception of file %1 from %2 finished") .arg(file->fileNum).arg(file->friendId); file->status = ToxFile::STOPPED; emit static_cast(core)->fileTransferFinished(*file); // confirm receive is complete - tox_file_send_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_FINISHED, nullptr, 0); + ///tox_file_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_FINISHED, nullptr, 0); removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); } - else if (receive_send == 0 && control_type == TOX_FILECONTROL_ACCEPT) + else if (receive_send == 0 && control_type == TOX_FILE_CONTROL_RESUME) { if (file->status == ToxFile::BROKEN) { @@ -645,11 +669,11 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive } emit static_cast(core)->fileTransferRemotePausedUnpaused(*file, false); } - else if ((receive_send == 0 || receive_send == 1) && control_type == TOX_FILECONTROL_PAUSE) + else if ((receive_send == 0 || receive_send == 1) && control_type == TOX_FILE_CONTROL_PAUSE) { emit static_cast(core)->fileTransferRemotePausedUnpaused(*file, true); } - else if (receive_send == 1 && control_type == TOX_FILECONTROL_RESUME_BROKEN) + else if (receive_send == 1 && control_type == TOX_FILE_CONTROL_RESUME) { if (length != sizeof(uint64_t)) return; @@ -661,7 +685,7 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive if (resumePos >= (unsigned)file->filesize) { qWarning() << "Core::onFileControlCallback: invalid resume position"; - tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); // don't sure about it + tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); // don't sure about it return; } @@ -669,7 +693,7 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive emit static_cast(core)->fileTransferBrokenUnbroken(*file, false); file->bytesSent = resumePos; - tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_ACCEPT, nullptr, 0); + tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); } else { @@ -678,7 +702,7 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive } } -void Core::onFileDataCallback(Tox*, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *core) +void Core::onFileDataCallback(Tox*, uint32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *core) { ToxFile* file{nullptr}; for (ToxFile& f : fileRecvQueue) @@ -701,9 +725,11 @@ void Core::onFileDataCallback(Tox*, int32_t friendnumber, uint8_t filenumber, co emit static_cast(core)->fileTransferInfo(*file); } -void Core::onAvatarInfoCallback(Tox*, int32_t friendnumber, uint8_t format, +void Core::onAvatarInfoCallback(Tox*, uint32_t friendnumber, uint8_t format, uint8_t* hash, void* _core) { + assert(0); + /* TODO: Address this avatar function Core* core = static_cast(_core); if (format == TOX_AVATAR_FORMAT_NONE) @@ -725,9 +751,10 @@ void Core::onAvatarInfoCallback(Tox*, int32_t friendnumber, uint8_t format, //else // qDebug() << "Core: Got same avatar info from" << core->getFriendUsername(friendnumber); } + */ } -void Core::onAvatarDataCallback(Tox*, int32_t friendnumber, uint8_t, +void Core::onAvatarDataCallback(Tox*, uint32_t friendnumber, uint8_t, uint8_t *hash, uint8_t *data, uint32_t datalen, void *core) { QPixmap pic; @@ -741,15 +768,15 @@ void Core::onAvatarDataCallback(Tox*, int32_t friendnumber, uint8_t, } } -void Core::onReadReceiptCallback(Tox*, int32_t friendnumber, uint32_t receipt, void *core) +void Core::onReadReceiptCallback(Tox*, uint32_t friendnumber, uint32_t receipt, void *core) { emit static_cast(core)->receiptRecieved(friendnumber, receipt); } void Core::acceptFriendRequest(const QString& userId) { - int friendId = tox_add_friend_norequest(tox, CUserId(userId).data()); - if (friendId == -1) { + uint32_t friendId = tox_friend_add_norequest(tox, CUserId(userId).data(), nullptr); + if (friendId == UINT32_MAX) { emit failedToAddFriend(userId); } else { saveConfiguration(); @@ -770,8 +797,9 @@ void Core::requestFriendship(const QString& friendAddress, const QString& messag qDebug() << "Core: requesting friendship of "+friendAddress; CString cMessage(message); - int friendId = tox_add_friend(tox, CFriendAddress(friendAddress).data(), cMessage.data(), cMessage.size()); - if (friendId < 0) + uint32_t friendId = tox_friend_add(tox, CFriendAddress(friendAddress).data(), + cMessage.data(), cMessage.size(), nullptr); + if (friendId == UINT32_MAX) { emit failedToAddFriend(userId); } @@ -789,28 +817,30 @@ void Core::requestFriendship(const QString& friendAddress, const QString& messag saveConfiguration(); } -int Core::sendMessage(int friendId, const QString& message) +int Core::sendMessage(uint32_t friendId, const QString& message) { QMutexLocker ml(&messageSendMutex); CString cMessage(message); - int receipt = tox_send_message(tox, friendId, cMessage.data(), cMessage.size()); + int receipt = tox_friend_send_message(tox, friendId, TOX_MESSAGE_TYPE_NORMAL, + cMessage.data(), cMessage.size(), nullptr); emit messageSentResult(friendId, message, receipt); return receipt; } -int Core::sendAction(int friendId, const QString &action) +int Core::sendAction(uint32_t friendId, const QString &action) { QMutexLocker ml(&messageSendMutex); CString cMessage(action); - int receipt = tox_send_action(tox, friendId, cMessage.data(), cMessage.size()); + int receipt = tox_friend_send_message(tox, friendId, TOX_MESSAGE_TYPE_ACTION, + cMessage.data(), cMessage.size(), nullptr); emit messageSentResult(friendId, action, receipt); return receipt; } -void Core::sendTyping(int friendId, bool typing) +void Core::sendTyping(uint32_t friendId, bool typing) { - int ret = tox_set_user_is_typing(tox, friendId, typing); - if (ret == -1) + bool ret = tox_self_set_typing(tox, friendId, typing, nullptr); + if (ret == false) emit failedToSetTyping(typing); } @@ -848,13 +878,14 @@ void Core::changeGroupTitle(int groupId, const QString& title) emit groupTitleChanged(groupId, getUsername(), title); } -void Core::sendFile(int32_t friendId, QString Filename, QString FilePath, long long filesize) +void Core::sendFile(uint32_t friendId, QString Filename, QString FilePath, long long filesize) { QMutexLocker mlocker(&fileSendMutex); QByteArray fileName = Filename.toUtf8(); - int fileNum = tox_new_file_sender(tox, friendId, filesize, (uint8_t*)fileName.data(), fileName.size()); - if (fileNum == -1) + uint32_t fileNum = tox_file_send(tox, friendId, TOX_FILE_KIND_DATA, filesize, nullptr, + (uint8_t*)fileName.data(), fileName.size(), nullptr); + if (fileNum == UINT32_MAX) { qWarning() << "Core::sendFile: Can't create the Tox file sender"; emit fileSendFailed(friendId, Filename); @@ -873,7 +904,7 @@ void Core::sendFile(int32_t friendId, QString Filename, QString FilePath, long l emit fileSendStarted(fileSendQueue.last()); } -void Core::pauseResumeFileSend(int friendId, int fileNum) +void Core::pauseResumeFileSend(uint32_t friendId, uint32_t fileNum) { ToxFile* file{nullptr}; for (ToxFile& f : fileSendQueue) @@ -893,19 +924,19 @@ void Core::pauseResumeFileSend(int friendId, int fileNum) { file->status = ToxFile::PAUSED; emit fileTransferPaused(*file); - tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_PAUSE, nullptr, 0); + tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_PAUSE, nullptr); } else if (file->status == ToxFile::PAUSED) { file->status = ToxFile::TRANSMITTING; emit fileTransferAccepted(*file); - tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_ACCEPT, nullptr, 0); + tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); } else qWarning() << "Core::pauseResumeFileSend: File is stopped"; } -void Core::pauseResumeFileRecv(int friendId, int fileNum) +void Core::pauseResumeFileRecv(uint32_t friendId, uint32_t fileNum) { ToxFile* file{nullptr}; for (ToxFile& f : fileRecvQueue) @@ -925,19 +956,19 @@ void Core::pauseResumeFileRecv(int friendId, int fileNum) { file->status = ToxFile::PAUSED; emit fileTransferPaused(*file); - tox_file_send_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_PAUSE, nullptr, 0); + tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_PAUSE, nullptr); } else if (file->status == ToxFile::PAUSED) { file->status = ToxFile::TRANSMITTING; emit fileTransferAccepted(*file); - tox_file_send_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_ACCEPT, nullptr, 0); + tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); } else qWarning() << "Core::pauseResumeFileRecv: File is stopped or broken"; } -void Core::cancelFileSend(int friendId, int fileNum) +void Core::cancelFileSend(uint32_t friendId, uint32_t fileNum) { ToxFile* file{nullptr}; for (ToxFile& f : fileSendQueue) @@ -955,12 +986,12 @@ void Core::cancelFileSend(int friendId, int fileNum) } file->status = ToxFile::STOPPED; emit fileTransferCancelled(*file); - tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); + tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); while (file->sendTimer) QThread::msleep(1); // Wait until sendAllFileData returns before deleting removeFileFromQueue(true, friendId, fileNum); } -void Core::cancelFileRecv(int friendId, int fileNum) +void Core::cancelFileRecv(uint32_t friendId, uint32_t fileNum) { ToxFile* file{nullptr}; for (ToxFile& f : fileRecvQueue) @@ -978,11 +1009,11 @@ void Core::cancelFileRecv(int friendId, int fileNum) } file->status = ToxFile::STOPPED; emit fileTransferCancelled(*file); - tox_file_send_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); + tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); removeFileFromQueue(true, friendId, fileNum); } -void Core::rejectFileRecvRequest(int friendId, int fileNum) +void Core::rejectFileRecvRequest(uint32_t friendId, uint32_t fileNum) { ToxFile* file{nullptr}; for (ToxFile& f : fileRecvQueue) @@ -1000,11 +1031,11 @@ void Core::rejectFileRecvRequest(int friendId, int fileNum) } file->status = ToxFile::STOPPED; emit fileTransferCancelled(*file); - tox_file_send_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); + tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); removeFileFromQueue(false, friendId, fileNum); } -void Core::acceptFileRecvRequest(int friendId, int fileNum, QString path) +void Core::acceptFileRecvRequest(uint32_t friendId, uint32_t fileNum, QString path) { ToxFile* file{nullptr}; for (ToxFile& f : fileRecvQueue) @@ -1028,14 +1059,14 @@ void Core::acceptFileRecvRequest(int friendId, int fileNum, QString path) } file->status = ToxFile::TRANSMITTING; emit fileTransferAccepted(*file); - tox_file_send_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_ACCEPT, nullptr, 0); + tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); } -void Core::removeFriend(int friendId, bool fake) +void Core::removeFriend(uint32_t friendId, bool fake) { if (!isReady() || fake) return; - if (tox_del_friend(tox, friendId) == -1) { + if (tox_friend_delete(tox, friendId, nullptr) == false) { emit failedToRemoveFriend(friendId); } else { saveConfiguration(); @@ -1056,10 +1087,10 @@ void Core::removeGroup(int groupId, bool fake) QString Core::getUsername() const { QString sname; - int size = tox_get_self_name_size(tox); + int size = tox_self_get_name_size(tox); uint8_t* name = new uint8_t[size]; - if (tox_get_self_name(tox, name) == size) - sname = CString::toString(name, size); + tox_self_get_name(tox, name); + sname = CString::toString(name, size); delete[] name; return sname; } @@ -1068,7 +1099,7 @@ void Core::setUsername(const QString& username) { CString cUsername(username); - if (tox_set_name(tox, cUsername.data(), cUsername.size()) == -1) { + if (tox_self_set_name(tox, cUsername.data(), cUsername.size(), nullptr) == false) { emit failedToSetUsername(username); } else { emit usernameSet(username); @@ -1076,13 +1107,9 @@ void Core::setUsername(const QString& username) } } -void Core::setAvatar(uint8_t format, const QByteArray& data) +void Core::setAvatar(const QByteArray& data) { - if (tox_set_avatar(tox, format, (uint8_t*)data.constData(), data.size()) != 0) - { - qWarning() << "Core: Failed to set self avatar"; - return; - } + /// TODO: Review this function, toxcore doesn't handle avatars anymore apparently. Good. QPixmap pic; pic.loadFromData(data); @@ -1091,15 +1118,15 @@ void Core::setAvatar(uint8_t format, const QByteArray& data) // Broadcast our new avatar! // according to tox.h, we need not broadcast this ourselves, but initial testing indicated elsewise - const uint32_t friendCount = tox_count_friendlist(tox);; + const uint32_t friendCount = tox_self_get_friend_list_size(tox); for (unsigned i=0; i Core::getKeypair() const if (!tox) return keypair; - char buf[2*TOX_PUBLIC_KEY_SIZE]; - tox_get_keys(tox, (uint8_t*)buf, (uint8_t*)buf+TOX_PUBLIC_KEY_SIZE); + char buf[std::max(TOX_PUBLIC_KEY_SIZE, TOX_SECRET_KEY_SIZE)]; + tox_self_get_public_key(tox, (uint8_t*)buf); keypair.first = QByteArray(buf, TOX_PUBLIC_KEY_SIZE); - keypair.second = QByteArray(buf+TOX_PUBLIC_KEY_SIZE, TOX_PUBLIC_KEY_SIZE); + tox_self_get_secret_key(tox, (uint8_t*)buf); + keypair.second = QByteArray(buf, TOX_SECRET_KEY_SIZE); return keypair; } QString Core::getStatusMessage() const { QString sname; - int size = tox_get_self_status_message_size(tox); + size_t size = tox_self_get_status_message_size(tox); uint8_t* name = new uint8_t[size]; - if (tox_get_self_status_message(tox, name, size) == size) - sname = CString::toString(name, size); + tox_self_get_status_message(tox, name); + sname = CString::toString(name, size); delete[] name; return sname; } @@ -1138,7 +1166,7 @@ void Core::setStatusMessage(const QString& message) { CString cMessage(message); - if (tox_set_status_message(tox, cMessage.data(), cMessage.size()) == -1) { + if (tox_self_set_status_message(tox, cMessage.data(), cMessage.size(), nullptr) == false) { emit failedToSetStatusMessage(message); } else { saveConfiguration(); @@ -1148,28 +1176,24 @@ void Core::setStatusMessage(const QString& message) void Core::setStatus(Status status) { - TOX_USERSTATUS userstatus; + TOX_USER_STATUS userstatus; switch (status) { case Status::Online: - userstatus = TOX_USERSTATUS_NONE; + userstatus = TOX_USER_STATUS_NONE; break; case Status::Away: - userstatus = TOX_USERSTATUS_AWAY; + userstatus = TOX_USER_STATUS_AWAY; break; case Status::Busy: - userstatus = TOX_USERSTATUS_BUSY; + userstatus = TOX_USER_STATUS_BUSY; break; default: - userstatus = TOX_USERSTATUS_INVALID; break; } - if (tox_set_user_status(tox, userstatus) == 0) { - saveConfiguration(); - emit statusSet(status); - } else { - emit failedToSetStatus(status); - } + tox_self_set_status(tox, userstatus); + saveConfiguration(); + emit statusSet(status); } void Core::onFileTransferFinished(ToxFile file) @@ -1194,8 +1218,9 @@ QString Core::sanitize(QString name) return name; } -bool Core::loadConfiguration(QString path) +QByteArray Core::loadToxSave(QString path) { + QByteArray data; loadPath = ""; // if not empty upon return, then user forgot a password and is switching QFile configurationFile(path); @@ -1203,17 +1228,18 @@ bool Core::loadConfiguration(QString path) if (!configurationFile.exists()) { qWarning() << "The Tox configuration file was not found"; - return true; + return data; } if (!configurationFile.open(QIODevice::ReadOnly)) { qCritical() << "File " << path << " cannot be opened"; - return true; + return data; } qint64 fileSize = configurationFile.size(); if (fileSize > 0) { - QByteArray data = configurationFile.readAll(); + data = configurationFile.readAll(); + /* TODO: Clean this up int error = tox_load(tox, reinterpret_cast(data.data()), data.size()); if (error < 0) { @@ -1236,28 +1262,11 @@ bool Core::loadConfiguration(QString path) return false; } } + */ } configurationFile.close(); - // set GUI with user and statusmsg - QString name = getUsername(); - if (!name.isEmpty()) - emit usernameSet(name); - - QString msg = getStatusMessage(); - if (!msg.isEmpty()) - emit statusMessageSet(msg); - - QString id = getSelfId().toString(); - if (!id.isEmpty()) - emit idSet(id); - - // tox core is already decrypted - if (Settings::getInstance().getEnableLogging() && Settings::getInstance().getEncryptLogs()) - checkEncryptedHistory(); - - loadFriends(); - return true; + return data; } void Core::saveConfiguration() @@ -1328,29 +1337,28 @@ void Core::switchConfiguration(const QString& profile) void Core::loadFriends() { - const uint32_t friendCount = tox_count_friendlist(tox); + const uint32_t friendCount = tox_self_get_friend_list_size(tox); if (friendCount > 0) { // assuming there are not that many friends to fill up the whole stack - int32_t *ids = new int32_t[friendCount]; - tox_get_friendlist(tox, ids, friendCount); + uint32_t *ids = new uint32_t[friendCount]; + tox_self_get_friend_list(tox, ids); uint8_t clientId[TOX_PUBLIC_KEY_SIZE]; for (int32_t i = 0; i < static_cast(friendCount); ++i) { - if (tox_get_client_id(tox, ids[i], clientId) == 0) { + if (tox_friend_get_public_key(tox, ids[i], clientId, nullptr)) { emit friendAdded(ids[i], CUserId::toString(clientId)); - const int nameSize = tox_get_name_size(tox, ids[i]); - if (nameSize > 0) { + const size_t nameSize = tox_friend_get_name_size(tox, ids[i], nullptr); + if (nameSize != SIZE_MAX) { uint8_t *name = new uint8_t[nameSize]; - if (tox_get_name(tox, ids[i], name) == nameSize) { + if (tox_friend_get_name(tox, ids[i], name, nullptr)) emit friendUsernameChanged(ids[i], CString::toString(name, nameSize)); - } delete[] name; } - const int statusMessageSize = tox_get_status_message_size(tox, ids[i]); - if (statusMessageSize > 0) { + const size_t statusMessageSize = tox_friend_get_status_message_size(tox, ids[i], nullptr); + if (statusMessageSize != SIZE_MAX) { uint8_t *statusMessage = new uint8_t[statusMessageSize]; - if (tox_get_status_message(tox, ids[i], statusMessage, statusMessageSize) == statusMessageSize) { + if (tox_friend_get_status_message(tox, ids[i], statusMessage, nullptr)) { emit friendStatusMessageChanged(ids[i], CString::toString(statusMessage, statusMessageSize)); } delete[] statusMessage; @@ -1364,9 +1372,9 @@ void Core::loadFriends() } } -void Core::checkLastOnline(int friendId) { - const uint64_t lastOnline = tox_get_last_online(tox, friendId); - if (lastOnline > 0) { +void Core::checkLastOnline(uint32_t friendId) { + const uint64_t lastOnline = tox_friend_get_last_online(tox, friendId, nullptr); + if (lastOnline != UINT64_MAX) { emit friendLastSeenChanged(friendId, QDateTime::fromTime_t(lastOnline)); } } @@ -1453,7 +1461,7 @@ void Core::quitGroupChat(int groupId) const tox_del_groupchat(tox, groupId); } -void Core::removeFileFromQueue(bool sendQueue, int friendId, int fileId) +void Core::removeFileFromQueue(bool sendQueue, uint32_t friendId, uint32_t fileId) { bool found = false; if (sendQueue) @@ -1492,6 +1500,8 @@ void Core::removeFileFromQueue(bool sendQueue, int friendId, int fileId) void Core::sendAllFileData(Core *core, ToxFile* file) { + assert(0); + /** TODO: Reimplement file transfers using tox_file_chunk_request_cb if (file->status == ToxFile::PAUSED) { file->sendTimer->start(5+TOX_FILE_INTERVAL); @@ -1513,7 +1523,7 @@ void Core::sendAllFileData(Core *core, ToxFile* file) qWarning("Core::fileHeartbeat: Error getting preffered chunk size, aborting file send"); file->status = ToxFile::STOPPED; emit core->fileTransferCancelled(*file); - tox_file_send_control(core->tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); removeFileFromQueue(true, file->friendId, file->fileNum); return; } @@ -1528,7 +1538,7 @@ void Core::sendAllFileData(Core *core, ToxFile* file) delete[] data; file->status = ToxFile::STOPPED; emit core->fileTransferCancelled(*file); - tox_file_send_control(core->tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); removeFileFromQueue(true, file->friendId, file->fileNum); return; } @@ -1538,7 +1548,7 @@ void Core::sendAllFileData(Core *core, ToxFile* file) delete[] data; file->status = ToxFile::STOPPED; emit core->fileTransferCancelled(*file); - tox_file_send_control(core->tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); removeFileFromQueue(true, file->friendId, file->fileNum); return; } @@ -1566,12 +1576,14 @@ void Core::sendAllFileData(Core *core, ToxFile* file) file->sendTimer->disconnect(); delete file->sendTimer; file->sendTimer = nullptr; - tox_file_send_control(core->tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_FINISHED, nullptr, 0); + /// TODO: Review this, we can't send finished messages anymore, but maybe we don't need to + ///tox_file_control(core->tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_FINISHED, nullptr, 0); //emit core->fileTransferFinished(*file); } + */ } -void Core::groupInviteFriend(int friendId, int groupId) +void Core::groupInviteFriend(uint32_t friendId, int groupId) { tox_invite_friend(tox, friendId, groupId); } @@ -1595,7 +1607,7 @@ void Core::createGroup(uint8_t type) bool Core::hasFriendWithAddress(const QString &addr) const { // Valid length check - if (addr.length() != (TOX_FRIEND_ADDRESS_SIZE * 2)) + if (addr.length() != (TOX_ADDRESS_SIZE * 2)) { return false; } @@ -1613,11 +1625,11 @@ bool Core::hasFriendWithPublicKey(const QString &pubkey) const } bool found = false; - const uint32_t friendCount = tox_count_friendlist(tox); + const size_t friendCount = tox_self_get_friend_list_size(tox); if (friendCount > 0) { - int32_t *ids = new int32_t[friendCount]; - tox_get_friendlist(tox, ids, friendCount); + uint32_t *ids = new uint32_t[friendCount]; + tox_self_get_friend_list(tox, ids); for (int32_t i = 0; i < static_cast(friendCount); ++i) { // getFriendAddress may return either id (public key) or address @@ -1637,11 +1649,14 @@ bool Core::hasFriendWithPublicKey(const QString &pubkey) const return found; } -QString Core::getFriendAddress(int friendNumber) const +QString Core::getFriendAddress(uint32_t friendNumber) const { // If we don't know the full address of the client, return just the id, otherwise get the full address uint8_t rawid[TOX_PUBLIC_KEY_SIZE]; - tox_get_client_id(tox, friendNumber, rawid); + if (!tox_friend_get_public_key(tox, friendNumber, rawid, nullptr)) { + qWarning() << "Core::getFriendAddress: Getting public key failed"; + return QString(); + } QByteArray data((char*)rawid,TOX_PUBLIC_KEY_SIZE); QString id = data.toHex().toUpper(); @@ -1652,11 +1667,18 @@ QString Core::getFriendAddress(int friendNumber) const return id; } -QString Core::getFriendUsername(int friendnumber) const +QString Core::getFriendUsername(uint32_t friendnumber) const { - uint8_t name[TOX_MAX_NAME_LENGTH]; - tox_get_name(tox, friendnumber, name); - return CString::toString(name, tox_get_name_size(tox, friendnumber)); + size_t namesize = tox_friend_get_name_size(tox, friendnumber, nullptr); + if (namesize == SIZE_MAX) { + qWarning() << "Core::getFriendUsername: Failed to get name size for friend "< Core::splitMessage(const QString &message, int maxLen) @@ -1693,22 +1715,22 @@ QString Core::getPeerName(const ToxID& id) const QString name; CUserId cid(id.toString()); - int friendId = tox_get_friend_number(tox, (uint8_t*)cid.data()); - if (friendId < 0) + uint32_t friendId = tox_friend_by_public_key(tox, (uint8_t*)cid.data(), nullptr); + if (friendId == UINT32_MAX) { qWarning() << "Core::getPeerName: No such peer "+id.toString(); return name; } - const int nameSize = tox_get_name_size(tox, friendId); - if (nameSize <= 0) + const size_t nameSize = tox_friend_get_name_size(tox, friendId, nullptr); + if (nameSize == SIZE_MAX) { //qDebug() << "Core::getPeerName: Can't get name of friend "+QString().setNum(friendId)+" ("+id.toString()+")"; return name; } uint8_t* cname = new uint8_t[nameSize(&nospam); std::reverse(nspm, nspm + 4); - tox_set_nospam(tox, nospam); + tox_self_set_nospam(tox, nospam); } void Core::resetCallSources() diff --git a/src/core.h b/src/core.h index 55094ec32..e1217d364 100644 --- a/src/core.h +++ b/src/core.h @@ -22,6 +22,7 @@ #include #include +#include #include "corestructs.h" #include "coreav.h" @@ -60,8 +61,8 @@ public: QString getGroupPeerName(int groupId, int peerId) const; ///< Get the name of a peer of a group ToxID getGroupPeerToxID(int groupId, int peerId) const; ///< Get the ToxID of a peer of a group QList getGroupPeerNames(int groupId) const; ///< Get the names of the peers of a group - QString getFriendAddress(int friendNumber) const; ///< Get the full address if known, or Tox ID of a friend - QString getFriendUsername(int friendNumber) const; ///< Get the username of a friend + QString getFriendAddress(uint32_t friendNumber) const; ///< Get the full address if known, or Tox ID of a friend + QString getFriendUsername(uint32_t friendNumber) const; ///< Get the username of a friend bool hasFriendWithAddress(const QString &addr) const; ///< Check if we have a friend by address bool hasFriendWithPublicKey(const QString &pubkey) const; ///< Check if we have a friend by public key int joinGroupchat(int32_t friendNumber, uint8_t type, const uint8_t* pubkey,uint16_t length) const; ///< Accept a groupchat invite @@ -93,37 +94,37 @@ public slots: void acceptFriendRequest(const QString& userId); void requestFriendship(const QString& friendAddress, const QString& message); - void groupInviteFriend(int friendId, int groupId); + void groupInviteFriend(uint32_t friendId, int groupId); void createGroup(uint8_t type = TOX_GROUPCHAT_TYPE_AV); - void removeFriend(int friendId, bool fake = false); + void removeFriend(uint32_t friendId, bool fake = false); void removeGroup(int groupId, bool fake = false); void setStatus(Status status); void setUsername(const QString& username); void setStatusMessage(const QString& message); - void setAvatar(uint8_t format, const QByteArray& data); + void setAvatar(const QByteArray& data); - int sendMessage(int friendId, const QString& message); + int sendMessage(uint32_t friendId, const QString& message); void sendGroupMessage(int groupId, const QString& message); void sendGroupAction(int groupId, const QString& message); void changeGroupTitle(int groupId, const QString& title); - int sendAction(int friendId, const QString& action); - void sendTyping(int friendId, bool typing); + int sendAction(uint32_t friendId, const QString& action); + void sendTyping(uint32_t friendId, bool typing); - void sendFile(int32_t friendId, QString Filename, QString FilePath, long long filesize); - void cancelFileSend(int friendId, int fileNum); - void cancelFileRecv(int friendId, int fileNum); - void rejectFileRecvRequest(int friendId, int fileNum); - void acceptFileRecvRequest(int friendId, int fileNum, QString path); - void pauseResumeFileSend(int friendId, int fileNum); - void pauseResumeFileRecv(int friendId, int fileNum); + void sendFile(uint32_t friendId, QString Filename, QString FilePath, long long filesize); + void cancelFileSend(uint32_t friendId, uint32_t fileNum); + void cancelFileRecv(uint32_t friendId, uint32_t fileNum); + void rejectFileRecvRequest(uint32_t friendId, uint32_t fileNum); + void acceptFileRecvRequest(uint32_t friendId, uint32_t fileNum, QString path); + void pauseResumeFileSend(uint32_t friendId, uint32_t fileNum); + void pauseResumeFileRecv(uint32_t friendId, uint32_t fileNum); void answerCall(int callId); void rejectCall(int callId); void hangupCall(int callId); - void startCall(int friendId, bool video=false); - void cancelCall(int callId, int friendId); + void startCall(uint32_t friendId, bool video=false); + void cancelCall(int callId, uint32_t friendId); void micMuteToggle(int callId); void volMuteToggle(int callId); @@ -151,23 +152,23 @@ signals: void blockingClearContacts(); void friendRequestReceived(const QString& userId, const QString& message); - void friendMessageReceived(int friendId, const QString& message, bool isAction); + void friendMessageReceived(uint32_t friendId, const QString& message, bool isAction); - void friendAdded(int friendId, const QString& userId); + void friendAdded(uint32_t friendId, const QString& userId); - void friendStatusChanged(int friendId, Status status); - void friendStatusMessageChanged(int friendId, const QString& message); - void friendUsernameChanged(int friendId, const QString& username); - void friendTypingChanged(int friendId, bool isTyping); - void friendAvatarChanged(int friendId, const QPixmap& pic); - void friendAvatarRemoved(int friendId); + void friendStatusChanged(uint32_t friendId, Status status); + void friendStatusMessageChanged(uint32_t friendId, const QString& message); + void friendUsernameChanged(uint32_t friendId, const QString& username); + void friendTypingChanged(uint32_t friendId, bool isTyping); + void friendAvatarChanged(uint32_t friendId, const QPixmap& pic); + void friendAvatarRemoved(uint32_t friendId); - void friendRemoved(int friendId); + void friendRemoved(uint32_t friendId); - void friendLastSeenChanged(int friendId, const QDateTime& dateTime); + void friendLastSeenChanged(uint32_t friendId, const QDateTime& dateTime); void emptyGroupCreated(int groupnumber); - void groupInviteReceived(int friendnumber, uint8_t type, QByteArray publicKey); + void groupInviteReceived(uint32_t friendNumber, uint8_t type, QByteArray publicKey); void groupMessageReceived(int groupnumber, int peernumber, const QString& message, bool isAction); void groupNamelistChanged(int groupnumber, int peernumber, uint8_t change); void groupTitleChanged(int groupnumber, const QString& author, const QString& title); @@ -179,14 +180,14 @@ signals: void idSet(const QString& id); void selfAvatarChanged(const QPixmap& pic); - void messageSentResult(int friendId, const QString& message, int messageId); + void messageSentResult(uint32_t friendId, const QString& message, int messageId); void groupSentResult(int groupId, const QString& message, int result); - void actionSentResult(int friendId, const QString& action, int success); + void actionSentResult(uint32_t friendId, const QString& action, int success); void receiptRecieved(int friedId, int receipt); void failedToAddFriend(const QString& userId, const QString& errorInfo = QString()); - void failedToRemoveFriend(int friendId); + void failedToRemoveFriend(uint32_t friendId); void failedToSetUsername(const QString& username); void failedToSetStatusMessage(const QString& message); void failedToSetStatus(Status status); @@ -207,45 +208,44 @@ signals: void fileTransferRemotePausedUnpaused(ToxFile file, bool paused); void fileTransferBrokenUnbroken(ToxFile file, bool broken); - void fileSendFailed(int FriendId, const QString& fname); + void fileSendFailed(uint32_t friendId, const QString& fname); - void avInvite(int friendId, int callIndex, bool video); - void avStart(int friendId, int callIndex, bool video); - void avCancel(int friendId, int callIndex); - void avEnd(int friendId, int callIndex); - void avRinging(int friendId, int callIndex, bool video); - void avStarting(int friendId, int callIndex, bool video); - void avEnding(int friendId, int callIndex); - void avRequestTimeout(int friendId, int callIndex); - void avPeerTimeout(int friendId, int callIndex); - void avMediaChange(int friendId, int callIndex, bool videoEnabled); - void avCallFailed(int friendId); - void avRejected(int friendId, int callIndex); + void avInvite(uint32_t friendId, int callIndex, bool video); + void avStart(uint32_t friendId, int callIndex, bool video); + void avCancel(uint32_t friendId, int callIndex); + void avEnd(uint32_t friendId, int callIndex); + void avRinging(uint32_t friendId, int callIndex, bool video); + void avStarting(uint32_t friendId, int callIndex, bool video); + void avEnding(uint32_t friendId, int callIndex); + void avRequestTimeout(uint32_t friendId, int callIndex); + void avPeerTimeout(uint32_t friendId, int callIndex); + void avMediaChange(uint32_t friendId, int callIndex, bool videoEnabled); + void avCallFailed(uint32_t friendId); + void avRejected(uint32_t friendId, int callIndex); void videoFrameReceived(vpx_image* frame); private: - static void onFriendRequest(Tox* tox, const uint8_t* cUserId, const uint8_t* cMessage, uint16_t cMessageSize, void* core); - static void onFriendMessage(Tox* tox, int friendId, const uint8_t* cMessage, uint16_t cMessageSize, void* core); - static void onFriendNameChange(Tox* tox, int friendId, const uint8_t* cName, uint16_t cNameSize, void* core); - static void onFriendTypingChange(Tox* tox, int friendId, uint8_t isTyping, void* core); - static void onStatusMessageChanged(Tox* tox, int friendId, const uint8_t* cMessage, uint16_t cMessageSize, void* core); - static void onUserStatusChanged(Tox* tox, int friendId, uint8_t userstatus, void* core); - static void onConnectionStatusChanged(Tox* tox, int friendId, uint8_t status, void* core); - static void onAction(Tox* tox, int friendId, const uint8_t* cMessage, uint16_t cMessageSize, void* core); + static void onFriendRequest(Tox* tox, const uint8_t* cUserId, const uint8_t* cMessage, size_t cMessageSize, void* core); + static void onFriendMessage(Tox* tox, uint32_t friendId, TOX_MESSAGE_TYPE type, const uint8_t* cMessage, size_t cMessageSize, void* core); + static void onFriendNameChange(Tox* tox, uint32_t friendId, const uint8_t* cName, size_t cNameSize, void* core); + static void onFriendTypingChange(Tox* tox, uint32_t friendId, bool isTyping, void* core); + static void onStatusMessageChanged(Tox* tox, uint32_t friendId, const uint8_t* cMessage, size_t cMessageSize, void* core); + static void onUserStatusChanged(Tox* tox, uint32_t friendId, TOX_USER_STATUS userstatus, void* core); + static void onConnectionStatusChanged(Tox* tox, uint32_t friendId, TOX_CONNECTION status, void* core); static void onGroupAction(Tox* tox, int groupnumber, int peernumber, const uint8_t * action, uint16_t length, void* core); - static void onGroupInvite(Tox *tox, int friendnumber, uint8_t type, const uint8_t *data, uint16_t length,void *userdata); + static void onGroupInvite(Tox *tox, int32_t friendNumber, uint8_t type, const uint8_t *data, uint16_t length, void *userdata); static void onGroupMessage(Tox *tox, int groupnumber, int friendgroupnumber, const uint8_t * message, uint16_t length, void *userdata); static void onGroupNamelistChange(Tox *tox, int groupnumber, int peernumber, uint8_t change, void *userdata); static void onGroupTitleChange(Tox*, int groupnumber, int peernumber, const uint8_t* title, uint8_t len, void* _core); - static void onFileSendRequestCallback(Tox *tox, int32_t friendnumber, uint8_t filenumber, uint64_t filesize, + static void onFileSendRequestCallback(Tox *tox, uint32_t friendnumber, uint8_t filenumber, uint64_t filesize, const uint8_t *filename, uint16_t filename_length, void *userdata); - static void onFileControlCallback(Tox *tox, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, + static void onFileControlCallback(Tox *tox, uint32_t friendnumber, uint8_t receive_send, uint8_t filenumber, uint8_t control_type, const uint8_t *data, uint16_t length, void *core); - static void onFileDataCallback(Tox *tox, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *userdata); - static void onAvatarInfoCallback(Tox* tox, int32_t friendnumber, uint8_t format, uint8_t *hash, void *userdata); - static void onAvatarDataCallback(Tox* tox, int32_t friendnumber, uint8_t format, uint8_t *hash, uint8_t *data, uint32_t datalen, void *userdata); - static void onReadReceiptCallback(Tox *tox, int32_t friendnumber, uint32_t receipt, void *core); + static void onFileDataCallback(Tox *tox, uint32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *userdata); + static void onAvatarInfoCallback(Tox* tox, uint32_t friendnumber, uint8_t format, uint8_t *hash, void *userdata); + static void onAvatarDataCallback(Tox* tox, uint32_t friendnumber, uint8_t format, uint8_t *hash, uint8_t *data, uint32_t datalen, void *userdata); + static void onReadReceiptCallback(Tox *tox, uint32_t friendnumber, uint32_t receipt, void *core); static void onAvInvite(void* toxav, int32_t call_index, void* core); static void onAvStart(void* toxav, int32_t call_index, void* core); @@ -259,7 +259,7 @@ private: static void sendGroupCallAudio(int groupId, ToxAv* toxav); - static void prepareCall(int friendId, int callId, ToxAv *toxav, bool videoEnabled); + static void prepareCall(uint32_t friendId, int callId, ToxAv *toxav, bool videoEnabled); static void cleanupCall(int callId); static void playCallAudio(void *toxav, int32_t callId, const int16_t *data, uint16_t samples, void *user_data); // Callback static void sendCallAudio(int callId, ToxAv* toxav); @@ -269,16 +269,16 @@ private: bool checkConnection(); - bool loadConfiguration(QString path); // Returns false for a critical error, true otherwise + QByteArray loadToxSave(QString path); bool loadEncryptedSave(QByteArray& data); void checkEncryptedHistory(); - void make_tox(); + void make_tox(QByteArray savedata); void loadFriends(); static void sendAllFileData(Core* core, ToxFile* file); - static void removeFileFromQueue(bool sendQueue, int friendId, int fileId); + static void removeFileFromQueue(bool sendQueue, uint32_t friendId, uint32_t fileId); - void checkLastOnline(int friendId); + void checkLastOnline(uint32_t friendId); void deadifyTox(); @@ -302,14 +302,14 @@ private: QMutex fileSendMutex, messageSendMutex; bool ready; - uint8_t* pwsaltedkeys[PasswordType::ptCounter] = {nullptr}; // use the pw's hash as the "pw" + TOX_PASS_KEY* pwsaltedkeys[PasswordType::ptCounter] = {nullptr}; // use the pw's hash as the "pw" // Hack for reloading current profile if switching to an encrypted one fails. // Testing the passwords before killing the current profile is perfectly doable, // however it would require major refactoring; // the Core class as a whole also requires major refactoring (especially to support multiple IDs at once), // so I'm punting on this until then, when it would get fixed anyways - uint8_t* backupkeys[PasswordType::ptCounter] = {nullptr}; + TOX_PASS_KEY* backupkeys[PasswordType::ptCounter] = {nullptr}; QString* backupProfile = nullptr; void saveCurrentInformation(); QString loadOldInformation(); diff --git a/src/coreav.cpp b/src/coreav.cpp index 3e9491bc0..bdd022b00 100644 --- a/src/coreav.cpp +++ b/src/coreav.cpp @@ -39,7 +39,7 @@ bool Core::anyActiveCalls() return false; } -void Core::prepareCall(int friendId, int callId, ToxAv* toxav, bool videoEnabled) +void Core::prepareCall(uint32_t friendId, int32_t callId, ToxAv* toxav, bool videoEnabled) { qDebug() << QString("Core: preparing call %1").arg(callId); calls[callId].callId = callId; @@ -120,9 +120,9 @@ fail: // Centralized error handling return; } -void Core::answerCall(int callId) +void Core::answerCall(int32_t callId) { - int friendId = toxav_get_peer_id(toxav, callId, 0); + uint32_t friendId = toxav_get_peer_id(toxav, callId, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV answer peer ID"; @@ -152,23 +152,23 @@ void Core::answerCall(int callId) delete transSettings; } -void Core::hangupCall(int callId) +void Core::hangupCall(int32_t callId) { qDebug() << QString("Core: hanging up call %1").arg(callId); calls[callId].active = false; toxav_hangup(toxav, callId); } -void Core::rejectCall(int callId) +void Core::rejectCall(int32_t callId) { qDebug() << QString("Core: rejecting call %1").arg(callId); calls[callId].active = false; toxav_reject(toxav, callId, nullptr); } -void Core::startCall(int friendId, bool video) +void Core::startCall(uint32_t friendId, bool video) { - int callId; + int32_t callId; ToxAvCSettings cSettings = av_DefaultSettings; cSettings.max_video_width = TOXAV_MAX_VIDEO_WIDTH; cSettings.max_video_height = TOXAV_MAX_VIDEO_HEIGHT; @@ -204,14 +204,14 @@ void Core::startCall(int friendId, bool video) } } -void Core::cancelCall(int callId, int friendId) +void Core::cancelCall(int32_t callId, uint32_t friendId) { qDebug() << QString("Core: Cancelling call with %1").arg(friendId); calls[callId].active = false; toxav_cancel(toxav, callId, friendId, nullptr); } -void Core::cleanupCall(int callId) +void Core::cleanupCall(int32_t callId) { qDebug() << QString("Core: cleaning up call %1").arg(callId); calls[callId].active = false; @@ -239,7 +239,7 @@ void Core::playCallAudio(void* toxav, int32_t callId, const int16_t *data, uint1 playAudioBuffer(calls[callId].alSource, data, samples, dest.audio_channels, dest.audio_sample_rate); } -void Core::sendCallAudio(int callId, ToxAv* toxav) +void Core::sendCallAudio(int32_t callId, ToxAv* toxav) { if (!calls[callId].active) return; @@ -303,7 +303,7 @@ void Core::playCallVideo(void*, int32_t callId, const vpx_image_t* img, void *us calls[callId].videoSource.pushVPXFrame(img); } -void Core::sendCallVideo(int callId) +void Core::sendCallVideo(int32_t callId) { if (!calls[callId].active || !calls[callId].videoEnabled) return; @@ -333,7 +333,7 @@ void Core::sendCallVideo(int callId) calls[callId].sendVideoTimer->start(); } -void Core::micMuteToggle(int callId) +void Core::micMuteToggle(int32_t callId) { if (calls[callId].active) { @@ -341,7 +341,7 @@ void Core::micMuteToggle(int callId) } } -void Core::volMuteToggle(int callId) +void Core::volMuteToggle(int32_t callId) { if (calls[callId].active) { @@ -354,7 +354,7 @@ void Core::onAvCancel(void* _toxav, int32_t callId, void* core) { ToxAv* toxav = static_cast(_toxav); - int friendId = toxav_get_peer_id(toxav, callId, 0); + uint32_t friendId = toxav_get_peer_id(toxav, callId, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV cancel"; @@ -379,7 +379,7 @@ void Core::onAvCancel(void* _toxav, int32_t callId, void* core) void Core::onAvReject(void* _toxav, int32_t callId, void* core) { ToxAv* toxav = static_cast(_toxav); - int friendId = toxav_get_peer_id(toxav, callId, 0); + uint32_t friendId = toxav_get_peer_id(toxav, callId, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV reject"; @@ -395,7 +395,7 @@ void Core::onAvEnd(void* _toxav, int32_t call_index, void* core) { ToxAv* toxav = static_cast(_toxav); - int friendId = toxav_get_peer_id(toxav, call_index, 0); + uint32_t friendId = toxav_get_peer_id(toxav, call_index, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV end"; @@ -412,7 +412,7 @@ void Core::onAvRinging(void* _toxav, int32_t call_index, void* core) { ToxAv* toxav = static_cast(_toxav); - int friendId = toxav_get_peer_id(toxav, call_index, 0); + uint32_t friendId = toxav_get_peer_id(toxav, call_index, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV ringing"; @@ -435,7 +435,7 @@ void Core::onAvRequestTimeout(void* _toxav, int32_t call_index, void* core) { ToxAv* toxav = static_cast(_toxav); - int friendId = toxav_get_peer_id(toxav, call_index, 0); + uint32_t friendId = toxav_get_peer_id(toxav, call_index, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV request timeout"; @@ -452,7 +452,7 @@ void Core::onAvPeerTimeout(void* _toxav, int32_t call_index, void* core) { ToxAv* toxav = static_cast(_toxav); - int friendId = toxav_get_peer_id(toxav, call_index, 0); + uint32_t friendId = toxav_get_peer_id(toxav, call_index, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV peer timeout"; @@ -470,7 +470,7 @@ void Core::onAvInvite(void* _toxav, int32_t call_index, void* core) { ToxAv* toxav = static_cast(_toxav); - int friendId = toxav_get_peer_id(toxav, call_index, 0); + uint32_t friendId = toxav_get_peer_id(toxav, call_index, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV invite"; @@ -504,7 +504,7 @@ void Core::onAvStart(void* _toxav, int32_t call_index, void* core) { ToxAv* toxav = static_cast(_toxav); - int friendId = toxav_get_peer_id(toxav, call_index, 0); + uint32_t friendId = toxav_get_peer_id(toxav, call_index, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV start"; diff --git a/src/coreav.h b/src/coreav.h index 4e196fc81..48c514808 100644 --- a/src/coreav.h +++ b/src/coreav.h @@ -19,8 +19,8 @@ struct ToxCall { ToxAvCSettings codecSettings; QTimer *sendAudioTimer, *sendVideoTimer; - int callId; - int friendId; + int32_t callId; + uint32_t friendId; bool videoEnabled; bool active; bool muteMic; diff --git a/src/coreencryption.cpp b/src/coreencryption.cpp index a69c1efdb..c77266be4 100644 --- a/src/coreencryption.cpp +++ b/src/coreencryption.cpp @@ -20,17 +20,18 @@ #include "core.h" #include "src/widget/gui.h" -#include -#include #include "src/misc/settings.h" #include "misc/cstring.h" #include "historykeeper.h" +#include +#include #include - #include #include #include #include +#include +#include void Core::setPassword(QString& password, PasswordType passtype, uint8_t* salt) { @@ -38,26 +39,25 @@ void Core::setPassword(QString& password, PasswordType passtype, uint8_t* salt) if (password.isEmpty()) return; - pwsaltedkeys[passtype] = new uint8_t[tox_pass_key_length()]; + pwsaltedkeys[passtype] = new TOX_PASS_KEY; CString str(password); if (salt) - tox_derive_key_with_salt(str.data(), str.size(), salt, pwsaltedkeys[passtype]); + tox_derive_key_with_salt(str.data(), str.size(), salt, pwsaltedkeys[passtype], nullptr); else - tox_derive_key_from_pass(str.data(), str.size(), pwsaltedkeys[passtype]); + tox_derive_key_from_pass(str.data(), str.size(), pwsaltedkeys[passtype], nullptr); password.clear(); } -#include void Core::useOtherPassword(PasswordType type) { clearPassword(type); - pwsaltedkeys[type] = new uint8_t[tox_pass_key_length()]; + pwsaltedkeys[type] = new TOX_PASS_KEY; PasswordType other = (type == ptMain) ? ptHistory : ptMain; - std::copy(pwsaltedkeys[other], pwsaltedkeys[other]+tox_pass_key_length(), pwsaltedkeys[type]); + std::copy(pwsaltedkeys[other], pwsaltedkeys[other]+TOX_PASS_KEY_LENGTH, pwsaltedkeys[type]); } void Core::clearPassword(PasswordType passtype) @@ -71,13 +71,13 @@ void Core::saveCurrentInformation() { if (pwsaltedkeys[ptMain]) { - backupkeys[ptMain] = new uint8_t[tox_pass_key_length()]; - std::copy(pwsaltedkeys[ptMain], pwsaltedkeys[ptMain]+tox_pass_key_length(), backupkeys[ptMain]); + backupkeys[ptMain] = new TOX_PASS_KEY; + std::copy(pwsaltedkeys[ptMain], pwsaltedkeys[ptMain]+TOX_PASS_KEY_LENGTH, backupkeys[ptMain]); } if (pwsaltedkeys[ptHistory]) { - backupkeys[ptHistory] = new uint8_t[tox_pass_key_length()]; - std::copy(pwsaltedkeys[ptHistory], pwsaltedkeys[ptHistory]+tox_pass_key_length(), backupkeys[ptHistory]); + backupkeys[ptHistory] = new TOX_PASS_KEY; + std::copy(pwsaltedkeys[ptHistory], pwsaltedkeys[ptHistory]+TOX_PASS_KEY_LENGTH, backupkeys[ptHistory]); } backupProfile = new QString(Settings::getInstance().getCurrentProfile()); } @@ -107,23 +107,24 @@ QByteArray Core::encryptData(const QByteArray& data, PasswordType passtype) { if (!pwsaltedkeys[passtype]) return QByteArray(); - uint8_t encrypted[data.size() + tox_pass_encryption_extra_length()]; - if (tox_pass_key_encrypt(reinterpret_cast(data.data()), data.size(), pwsaltedkeys[passtype], encrypted) == -1) + uint8_t encrypted[data.size() + TOX_PASS_ENCRYPTION_EXTRA_LENGTH]; + if (!tox_pass_key_encrypt(reinterpret_cast(data.data()), data.size(), + pwsaltedkeys[passtype], encrypted, nullptr)) { qWarning() << "Core::encryptData: encryption failed"; return QByteArray(); } - return QByteArray(reinterpret_cast(encrypted), data.size() + tox_pass_encryption_extra_length()); + return QByteArray(reinterpret_cast(encrypted), data.size() + TOX_PASS_ENCRYPTION_EXTRA_LENGTH); } QByteArray Core::decryptData(const QByteArray& data, PasswordType passtype) { if (!pwsaltedkeys[passtype]) return QByteArray(); - int sz = data.size() - tox_pass_encryption_extra_length(); + int sz = data.size() - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; uint8_t decrypted[sz]; - int decr_size = tox_pass_key_decrypt(reinterpret_cast(data.data()), data.size(), pwsaltedkeys[passtype], decrypted); - if (decr_size != sz) + if (!tox_pass_key_decrypt(reinterpret_cast(data.data()), data.size(), + pwsaltedkeys[passtype], decrypted, nullptr)) { qWarning() << "Core::decryptData: decryption failed"; return QByteArray(); @@ -147,10 +148,10 @@ QByteArray Core::getSaltFromFile(QString filename) qWarning() << "Core: file" << filename << "doesn't exist"; return QByteArray(); } - QByteArray data = file.read(tox_pass_encryption_extra_length()); + QByteArray data = file.read(TOX_PASS_ENCRYPTION_EXTRA_LENGTH); file.close(); - uint8_t *salt = new uint8_t[tox_pass_salt_length()]; + uint8_t *salt = new uint8_t[TOX_PASS_SALT_LENGTH]; int err = tox_get_salt(reinterpret_cast(data.data()), salt); if (err) { @@ -158,13 +159,15 @@ QByteArray Core::getSaltFromFile(QString filename) return QByteArray(); } - QByteArray res = QByteArray::fromRawData(reinterpret_cast(salt), tox_pass_salt_length()); + QByteArray res = QByteArray::fromRawData(reinterpret_cast(salt), TOX_PASS_SALT_LENGTH); delete[] salt; return res; } bool Core::loadEncryptedSave(QByteArray& data) { + assert(0); + /* if (!Settings::getInstance().getEncryptTox()) GUI::showWarning(tr("Encryption error"), tr("The .tox file is encrypted, but encryption was not checked, continuing regardless.")); @@ -186,7 +189,7 @@ bool Core::loadEncryptedSave(QByteArray& data) else dialogtxt = a; - uint8_t salt[tox_pass_salt_length()]; + uint8_t salt[TOX_PASS_SALT_LENGTH]; tox_get_salt(reinterpret_cast(data.data()), salt); do @@ -207,6 +210,7 @@ bool Core::loadEncryptedSave(QByteArray& data) Settings::getInstance().setEncryptTox(true); return true; + */ } void Core::checkEncryptedHistory() @@ -290,11 +294,15 @@ void Core::saveConfiguration(const QString& path) qDebug() << "Core: writing tox_save to " << path; - uint32_t fileSize; bool encrypt = Settings::getInstance().getEncryptTox(); + uint32_t fileSize; + bool encrypt = Settings::getInstance().getEncryptTox(); if (encrypt) - fileSize = tox_encrypted_size(tox); + { + qCritical() << "Encrypted saving not implemented!"; + exit(-1); + } else - fileSize = tox_size(tox); + fileSize = tox_get_savedata_size(tox); if (fileSize > 0 && fileSize <= std::numeric_limits::max()) { uint8_t *data = new uint8_t[fileSize]; @@ -306,20 +314,24 @@ void Core::saveConfiguration(const QString& path) // probably zero chance event GUI::showWarning(tr("NO Password"), tr("Local file encryption is enabled, but there is no password! It will be disabled.")); Settings::getInstance().setEncryptTox(false); - tox_save(tox, data); + tox_get_savedata(tox, data); } else { + qCritical() << "Encryption not implemented"; + exit(-1); + /* int ret = tox_encrypted_key_save(tox, data, pwsaltedkeys[ptMain]); if (ret == -1) { qCritical() << "Core::saveConfiguration: encryption of save file failed!!!"; return; } + */ } } else - tox_save(tox, data); + tox_get_savedata(tox, data); configurationFile.write(reinterpret_cast(data), fileSize); configurationFile.commit(); diff --git a/src/corestructs.cpp b/src/corestructs.cpp index 980fd1301..d58aacfa6 100644 --- a/src/corestructs.cpp +++ b/src/corestructs.cpp @@ -4,9 +4,9 @@ #include #include -#define TOX_ID_LENGTH 2*TOX_FRIEND_ADDRESS_SIZE +#define TOX_HEX_ID_LENGTH 2*TOX_ADDRESS_SIZE -ToxFile::ToxFile(int FileNum, int FriendId, QByteArray FileName, QString FilePath, FileDirection Direction) +ToxFile::ToxFile(uint32_t FileNum, uint32_t FriendId, QByteArray FileName, QString FilePath, FileDirection Direction) : fileNum(FileNum), friendId(FriendId), fileName{FileName}, filePath{FilePath}, file{new QFile(filePath)}, bytesSent{0}, filesize{0}, status{STOPPED}, direction{Direction}, sendTimer{nullptr} { @@ -78,5 +78,5 @@ void ToxID::clear() bool ToxID::isToxId(const QString& value) { const QRegularExpression hexRegExp("^[A-Fa-f0-9]+$"); - return value.length() == TOX_ID_LENGTH && value.contains(hexRegExp); + return value.length() == TOX_HEX_ID_LENGTH && value.contains(hexRegExp); } diff --git a/src/corestructs.h b/src/corestructs.h index 657d58f7b..d6bc81ae3 100644 --- a/src/corestructs.h +++ b/src/corestructs.h @@ -58,7 +58,7 @@ struct ToxFile }; ToxFile()=default; - ToxFile(int FileNum, int FriendId, QByteArray FileName, QString FilePath, FileDirection Direction); + ToxFile(uint32_t FileNum, uint32_t FriendId, QByteArray FileName, QString FilePath, FileDirection Direction); ~ToxFile(){} bool operator==(const ToxFile& other) const; @@ -67,8 +67,8 @@ struct ToxFile void setFilePath(QString path); bool open(bool write); - int fileNum; - int friendId; + uint32_t fileNum; + uint32_t friendId; QByteArray fileName; QString filePath; QFile* file; diff --git a/src/friend.cpp b/src/friend.cpp index 272cdcb1c..767b62010 100644 --- a/src/friend.cpp +++ b/src/friend.cpp @@ -22,7 +22,7 @@ #include "src/core.h" #include "src/misc/settings.h" -Friend::Friend(int FriendId, const ToxID &UserId) +Friend::Friend(uint32_t FriendId, const ToxID &UserId) : userName{Core::getInstance()->getPeerName(UserId)}, userID{UserId}, friendId{FriendId} { @@ -95,7 +95,7 @@ const ToxID &Friend::getToxID() const return userID; } -int Friend::getFriendID() const +uint32_t Friend::getFriendID() const { return friendId; } diff --git a/src/friend.h b/src/friend.h index b6ce04a89..cdf756bf3 100644 --- a/src/friend.h +++ b/src/friend.h @@ -28,7 +28,7 @@ class Friend : public QObject { Q_OBJECT public: - Friend(int FriendId, const ToxID &UserId); + Friend(uint32_t FriendId, const ToxID &UserId); Friend(const Friend& other)=delete; ~Friend(); Friend& operator=(const Friend& other)=delete; @@ -43,7 +43,7 @@ public: int getEventFlag() const; const ToxID &getToxID() const; - int getFriendID() const; + uint32_t getFriendID() const; void setStatus(Status s); Status getStatus() const; @@ -57,7 +57,7 @@ signals: private: QString userAlias, userName; ToxID userID; - int friendId; + uint32_t friendId; int hasNewEvents; Status friendStatus; diff --git a/src/friendlist.h b/src/friendlist.h index 9e6807197..5db698db3 100644 --- a/src/friendlist.h +++ b/src/friendlist.h @@ -19,7 +19,7 @@ template class QList; template class QHash; -struct Friend; +class Friend; class QString; struct ToxID; diff --git a/src/group.h b/src/group.h index f28c32685..bc9fcc73e 100644 --- a/src/group.h +++ b/src/group.h @@ -23,7 +23,7 @@ #define RETRY_PEER_INFO_INTERVAL 500 -struct Friend; +class Friend; class GroupWidget; class GroupChatForm; struct ToxID; diff --git a/src/misc/cdata.cpp b/src/misc/cdata.cpp index 28025de94..9ff8cc722 100644 --- a/src/misc/cdata.cpp +++ b/src/misc/cdata.cpp @@ -72,7 +72,7 @@ QString CUserId::toString(const uint8_t* cUserId) // CFriendAddress -const uint16_t CFriendAddress::SIZE{TOX_FRIEND_ADDRESS_SIZE}; +const uint16_t CFriendAddress::SIZE{TOX_ADDRESS_SIZE}; CFriendAddress::CFriendAddress(const QString &friendAddress) : CData(friendAddress, SIZE) diff --git a/src/misc/db/encrypteddb.cpp b/src/misc/db/encrypteddb.cpp index 709608667..1a8427aef 100644 --- a/src/misc/db/encrypteddb.cpp +++ b/src/misc/db/encrypteddb.cpp @@ -25,7 +25,7 @@ #include qint64 EncryptedDb::encryptedChunkSize = 4096; -qint64 EncryptedDb::plainChunkSize = EncryptedDb::encryptedChunkSize - tox_pass_encryption_extra_length(); +qint64 EncryptedDb::plainChunkSize = EncryptedDb::encryptedChunkSize - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; EncryptedDb::EncryptedDb(const QString &fname, QList initList) : PlainDb(":memory:", initList), fileName(fname) diff --git a/src/nexus.cpp b/src/nexus.cpp index 72ffb96c5..b7207f8df 100644 --- a/src/nexus.cpp +++ b/src/nexus.cpp @@ -47,6 +47,7 @@ void Nexus::start() qRegisterMetaType("vpx_image"); qRegisterMetaType("uint8_t"); qRegisterMetaType("uint16_t"); + qRegisterMetaType("uint32_t"); qRegisterMetaType("const int16_t*"); qRegisterMetaType("int32_t"); qRegisterMetaType("int64_t"); @@ -119,8 +120,8 @@ void Nexus::start() connect(core, &Core::blockingClearContacts, widget, &Widget::clearContactsList, Qt::BlockingQueuedConnection); connect(core, &Core::friendTypingChanged, widget, &Widget::onFriendTypingChanged); - connect(core, SIGNAL(messageSentResult(int,QString,int)), widget, SLOT(onMessageSendResult(int,QString,int))); - connect(core, SIGNAL(groupSentResult(int,QString,int)), widget, SLOT(onGroupSendResult(int,QString,int))); + connect(core, &Core::messageSentResult, widget, &Widget::onMessageSendResult); + connect(core, &Core::groupSentResult, widget, &Widget::onGroupSendResult); connect(widget, &Widget::statusSet, core, &Core::setStatus); connect(widget, &Widget::friendRequested, core, &Core::requestFriendship); diff --git a/src/offlinemsgengine.h b/src/offlinemsgengine.h index 52e1f8dd5..b7f9f6f17 100644 --- a/src/offlinemsgengine.h +++ b/src/offlinemsgengine.h @@ -24,7 +24,7 @@ #include #include "src/chatlog/chatmessage.h" -struct Friend; +class Friend; class QTimer; class OfflineMsgEngine : public QObject diff --git a/src/toxdns.cpp b/src/toxdns.cpp index 11cd1670f..ab08b8e2d 100644 --- a/src/toxdns.cpp +++ b/src/toxdns.cpp @@ -24,7 +24,7 @@ #include #include -#define TOX_ID_LENGTH 2*TOX_FRIEND_ADDRESS_SIZE +#define TOX_HEX_ID_LENGTH 2*TOX_ADDRESS_SIZE const ToxDNS::tox3_server ToxDNS::pinnedServers[] { @@ -128,13 +128,13 @@ QString ToxDNS::queryTox1(const QString& record, bool silent) } idx += 3; - if (entry.length() < idx + static_cast(TOX_ID_LENGTH)) { + if (entry.length() < idx + static_cast(TOX_HEX_ID_LENGTH)) { if (!silent) showWarning(tr("The DNS lookup does not contain a valid Tox ID", "Error with the DNS")); return toxId; } - toxId = entry.mid(idx, TOX_ID_LENGTH); + toxId = entry.mid(idx, TOX_HEX_ID_LENGTH); if (!ToxID::isToxId(toxId)) { if (!silent) showWarning(tr("The DNS lookup does not contain a valid Tox ID", "Error with the DNS")); @@ -201,7 +201,7 @@ QString ToxDNS::queryTox3(const tox3_server& server, const QString &record, bool idx += 3; id = entry.mid(idx).toUtf8(); - uint8_t toxId[TOX_FRIEND_ADDRESS_SIZE]; + uint8_t toxId[TOX_ADDRESS_SIZE]; toxIdSize = tox_decrypt_dns3_TXT(tox_dns3, toxId, (uint8_t*)id.data(), id.size(), request_id); if (toxIdSize < 0) // We can always fallback on tox1 if toxdns3 fails { diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 48208c808..3097eaac8 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -254,7 +254,7 @@ void ChatForm::onFileRecvRequest(ToxFile file) } } -void ChatForm::onAvInvite(int FriendId, int CallId, bool video) +void ChatForm::onAvInvite(uint32_t FriendId, int CallId, bool video) { if (FriendId != f->getFriendID()) return; @@ -306,7 +306,7 @@ void ChatForm::onAvInvite(int FriendId, int CallId, bool video) } } -void ChatForm::onAvStart(int FriendId, int CallId, bool video) +void ChatForm::onAvStart(uint32_t FriendId, int CallId, bool video) { if (FriendId != f->getFriendID()) return; @@ -357,7 +357,7 @@ void ChatForm::onAvStart(int FriendId, int CallId, bool video) startCounter(); } -void ChatForm::onAvCancel(int FriendId, int) +void ChatForm::onAvCancel(uint32_t FriendId, int) { if (FriendId != f->getFriendID()) return; @@ -375,7 +375,7 @@ void ChatForm::onAvCancel(int FriendId, int) addSystemInfoMessage(tr("%1 stopped calling").arg(f->getDisplayedName()), ChatMessage::INFO, QDateTime::currentDateTime()); } -void ChatForm::onAvEnd(int FriendId, int) +void ChatForm::onAvEnd(uint32_t FriendId, int) { if (FriendId != f->getFriendID()) return; @@ -390,7 +390,7 @@ void ChatForm::onAvEnd(int FriendId, int) netcam->hide(); } -void ChatForm::onAvRinging(int FriendId, int CallId, bool video) +void ChatForm::onAvRinging(uint32_t FriendId, int CallId, bool video) { if (FriendId != f->getFriendID()) return; @@ -426,7 +426,7 @@ void ChatForm::onAvRinging(int FriendId, int CallId, bool video) addSystemInfoMessage(tr("Calling to %1").arg(f->getDisplayedName()), ChatMessage::INFO, QDateTime::currentDateTime()); } -void ChatForm::onAvStarting(int FriendId, int CallId, bool video) +void ChatForm::onAvStarting(uint32_t FriendId, int CallId, bool video) { if (FriendId != f->getFriendID()) return; @@ -461,7 +461,7 @@ void ChatForm::onAvStarting(int FriendId, int CallId, bool video) startCounter(); } -void ChatForm::onAvEnding(int FriendId, int) +void ChatForm::onAvEnding(uint32_t FriendId, int) { if (FriendId != f->getFriendID()) return; @@ -477,7 +477,7 @@ void ChatForm::onAvEnding(int FriendId, int) netcam->hide(); } -void ChatForm::onAvRequestTimeout(int FriendId, int) +void ChatForm::onAvRequestTimeout(uint32_t FriendId, int) { if (FriendId != f->getFriendID()) return; @@ -493,7 +493,7 @@ void ChatForm::onAvRequestTimeout(int FriendId, int) netcam->hide(); } -void ChatForm::onAvPeerTimeout(int FriendId, int) +void ChatForm::onAvPeerTimeout(uint32_t FriendId, int) { if (FriendId != f->getFriendID()) return; @@ -509,7 +509,7 @@ void ChatForm::onAvPeerTimeout(int FriendId, int) netcam->hide(); } -void ChatForm::onAvRejected(int FriendId, int) +void ChatForm::onAvRejected(uint32_t FriendId, int) { if (FriendId != f->getFriendID()) return; @@ -526,7 +526,7 @@ void ChatForm::onAvRejected(int FriendId, int) netcam->hide(); } -void ChatForm::onAvMediaChange(int FriendId, int CallId, bool video) +void ChatForm::onAvMediaChange(uint32_t FriendId, int CallId, bool video) { if (FriendId != f->getFriendID() || CallId != callId) return; @@ -601,7 +601,7 @@ void ChatForm::onCallTriggered() audioOutputFlag = true; callButton->disconnect(); videoButton->disconnect(); - emit startCall(f->getFriendID()); + emit startCall(f->getFriendID(), false); } void ChatForm::onVideoCallTriggered() @@ -612,10 +612,10 @@ void ChatForm::onVideoCallTriggered() audioOutputFlag = true; callButton->disconnect(); videoButton->disconnect(); - emit startVideoCall(f->getFriendID(), true); + emit startCall(f->getFriendID(), true); } -void ChatForm::onAvCallFailed(int FriendId) +void ChatForm::onAvCallFailed(uint32_t FriendId) { if (FriendId != f->getFriendID()) return; @@ -737,7 +737,7 @@ void ChatForm::onVolMuteToggle() } } -void ChatForm::onFileSendFailed(int FriendId, const QString &fname) +void ChatForm::onFileSendFailed(uint32_t FriendId, const QString &fname) { if (FriendId != f->getFriendID()) return; @@ -745,7 +745,7 @@ void ChatForm::onFileSendFailed(int FriendId, const QString &fname) addSystemInfoMessage(tr("Failed to send file \"%1\"").arg(fname), ChatMessage::ERROR, QDateTime::currentDateTime()); } -void ChatForm::onAvatarChange(int FriendId, const QPixmap &pic) +void ChatForm::onAvatarChange(uint32_t FriendId, const QPixmap &pic) { if (FriendId != f->getFriendID()) return; @@ -787,7 +787,7 @@ void ChatForm::dropEvent(QDropEvent *ev) } } -void ChatForm::onAvatarRemoved(int FriendId) +void ChatForm::onAvatarRemoved(uint32_t FriendId) { if (FriendId != f->getFriendID()) return; diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h index 7be0427b3..0af254646 100644 --- a/src/widget/form/chatform.h +++ b/src/widget/form/chatform.h @@ -25,7 +25,7 @@ #include -struct Friend; +class Friend; class FileTransferInstance; class NetCamView; class QPixmap; @@ -50,12 +50,11 @@ public: virtual void show(Ui::MainWindow &ui); signals: - void sendFile(int32_t friendId, QString, QString, long long); - void startCall(int friendId); - void startVideoCall(int friendId, bool video); + void sendFile(uint32_t friendId, QString, QString, long long); + void startCall(uint32_t FriendId, bool video); void answerCall(int callId); void hangupCall(int callId); - void cancelCall(int callId, int friendId); + void cancelCall(int callId, uint32_t FriendId); void rejectCall(int callId); void micMuteToggle(int callId); void volMuteToggle(int callId); @@ -64,22 +63,22 @@ signals: public slots: void startFileSend(ToxFile file); void onFileRecvRequest(ToxFile file); - void onAvInvite(int FriendId, int CallId, bool video); - void onAvStart(int FriendId, int CallId, bool video); - void onAvCancel(int FriendId, int CallId); - void onAvEnd(int FriendId, int CallId); - void onAvRinging(int FriendId, int CallId, bool video); - void onAvStarting(int FriendId, int CallId, bool video); - void onAvEnding(int FriendId, int CallId); - void onAvRequestTimeout(int FriendId, int CallId); - void onAvPeerTimeout(int FriendId, int CallId); - void onAvMediaChange(int FriendId, int CallId, bool video); - void onAvCallFailed(int FriendId); - void onAvRejected(int FriendId, int CallId); + void onAvInvite(uint32_t FriendId, int CallId, bool video); + void onAvStart(uint32_t FriendId, int CallId, bool video); + void onAvCancel(uint32_t FriendId, int CallId); + void onAvEnd(uint32_t FriendId, int CallId); + void onAvRinging(uint32_t FriendId, int CallId, bool video); + void onAvStarting(uint32_t FriendId, int CallId, bool video); + void onAvEnding(uint32_t FriendId, int CallId); + void onAvRequestTimeout(uint32_t FriendId, int CallId); + void onAvPeerTimeout(uint32_t FriendId, int CallId); + void onAvMediaChange(uint32_t FriendId, int CallId, bool video); + void onAvCallFailed(uint32_t FriendId); + void onAvRejected(uint32_t FriendId, int CallId); void onMicMuteToggle(); void onVolMuteToggle(); - void onAvatarChange(int FriendId, const QPixmap& pic); - void onAvatarRemoved(int FriendId); + void onAvatarChange(uint32_t FriendId, const QPixmap& pic); + void onAvatarRemoved(uint32_t FriendId); private slots: void onSendTriggered(); @@ -91,7 +90,7 @@ private slots: void onHangupCallTriggered(); void onCancelCallTriggered(); void onRejectCallTriggered(); - void onFileSendFailed(int FriendId, const QString &fname); + void onFileSendFailed(uint32_t FriendId, const QString &fname); void onLoadHistory(); void onUpdateTime(); void onEnableCallButtons(); diff --git a/src/widget/form/genericchatform.h b/src/widget/form/genericchatform.h index 499daee3b..d5bb407a3 100644 --- a/src/widget/form/genericchatform.h +++ b/src/widget/form/genericchatform.h @@ -60,8 +60,8 @@ public: ChatLog* getChatLog() const; signals: - void sendMessage(int, QString); - void sendAction(int, QString); + void sendMessage(uint32_t, QString); + void sendAction(uint32_t, QString); void chatAreaCleared(); public slots: diff --git a/src/widget/form/profileform.cpp b/src/widget/form/profileform.cpp index 7d7d09920..68c5bc06a 100644 --- a/src/widget/form/profileform.cpp +++ b/src/widget/form/profileform.cpp @@ -214,22 +214,7 @@ void ProfileForm::onAvatarClicked() pic.save(&buffer, "PNG"); buffer.close(); - if (bytes.size() >= TOX_AVATAR_MAX_DATA_LENGTH) - { - pic = pic.scaled(64,64, Qt::KeepAspectRatio, Qt::SmoothTransformation); - bytes.clear(); - buffer.open(QIODevice::WriteOnly); - pic.save(&buffer, "PNG"); - buffer.close(); - } - - if (bytes.size() >= TOX_AVATAR_MAX_DATA_LENGTH) - { - GUI::showError(tr("Error"), tr("This image is too big")); - return; - } - - Nexus::getCore()->setAvatar(TOX_AVATAR_FORMAT_PNG, bytes); + Nexus::getCore()->setAvatar(bytes); } void ProfileForm::onLoadClicked() diff --git a/src/widget/friendlistwidget.cpp b/src/widget/friendlistwidget.cpp index ad665666a..5a5e481bb 100644 --- a/src/widget/friendlistwidget.cpp +++ b/src/widget/friendlistwidget.cpp @@ -87,7 +87,7 @@ void FriendListWidget::onGroupchatPositionChanged(bool top) } } -void FriendListWidget::moveWidget(QWidget *w, Status s, int hasNewEvents) +void FriendListWidget::moveWidget(QWidget *w, Status s) { QVBoxLayout* l = getFriendLayout(s); l->removeWidget(w); diff --git a/src/widget/friendlistwidget.h b/src/widget/friendlistwidget.h index 70101b885..56aa4deee 100644 --- a/src/widget/friendlistwidget.h +++ b/src/widget/friendlistwidget.h @@ -37,7 +37,7 @@ signals: public slots: void onGroupchatPositionChanged(bool top); - void moveWidget(QWidget *w, Status s, int hasNewEvents); + void moveWidget(QWidget *w, Status s); private: QHash layouts; diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index fdb4e5591..8e08f1f41 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -580,7 +580,7 @@ void Widget::addFriend(int friendId, const QString &userId) //qDebug() << "Widget: Adding friend with id" << userId; ToxID userToxId = ToxID::fromString(userId); Friend* newfriend = FriendList::addFriend(friendId, userToxId); - contactListWidget->moveWidget(newfriend->getFriendWidget(),Status::Offline,0); + contactListWidget->moveWidget(newfriend->getFriendWidget(),Status::Offline); Core* core = Nexus::getCore(); connect(newfriend, &Friend::displayedNameChanged, contactListWidget, &FriendListWidget::moveWidget); @@ -589,17 +589,16 @@ void Widget::addFriend(int friendId, const QString &userId) connect(newfriend->getFriendWidget(), SIGNAL(removeFriend(int)), this, SLOT(removeFriend(int))); connect(newfriend->getFriendWidget(), SIGNAL(copyFriendIdToClipboard(int)), this, SLOT(copyFriendIdToClipboard(int))); connect(newfriend->getFriendWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*)), newfriend->getChatForm(), SLOT(focusInput())); - connect(newfriend->getChatForm(), SIGNAL(sendMessage(int,QString)), core, SLOT(sendMessage(int,QString))); + connect(newfriend->getChatForm(), &GenericChatForm::sendMessage, core, &Core::sendMessage); connect(newfriend->getChatForm(), &GenericChatForm::sendAction, core, &Core::sendAction); - connect(newfriend->getChatForm(), SIGNAL(sendFile(int32_t, QString, QString, long long)), core, SLOT(sendFile(int32_t, QString, QString, long long))); - connect(newfriend->getChatForm(), SIGNAL(answerCall(int)), core, SLOT(answerCall(int))); - connect(newfriend->getChatForm(), SIGNAL(hangupCall(int)), core, SLOT(hangupCall(int))); - connect(newfriend->getChatForm(), SIGNAL(rejectCall(int)), core, SLOT(rejectCall(int))); - connect(newfriend->getChatForm(), SIGNAL(startCall(int)), core, SLOT(startCall(int))); - connect(newfriend->getChatForm(), SIGNAL(startVideoCall(int,bool)), core, SLOT(startCall(int,bool))); - connect(newfriend->getChatForm(), SIGNAL(cancelCall(int,int)), core, SLOT(cancelCall(int,int))); - connect(newfriend->getChatForm(), SIGNAL(micMuteToggle(int)), core, SLOT(micMuteToggle(int))); - connect(newfriend->getChatForm(), SIGNAL(volMuteToggle(int)), core, SLOT(volMuteToggle(int))); + connect(newfriend->getChatForm(), &ChatForm::sendFile, core, &Core::sendFile); + connect(newfriend->getChatForm(), &ChatForm::answerCall, core, &Core::answerCall); + connect(newfriend->getChatForm(), &ChatForm::hangupCall, core, &Core::hangupCall); + connect(newfriend->getChatForm(), &ChatForm::rejectCall, core, &Core::rejectCall); + connect(newfriend->getChatForm(), &ChatForm::startCall, core, &Core::startCall); + connect(newfriend->getChatForm(), &ChatForm::cancelCall, core, &Core::cancelCall); + connect(newfriend->getChatForm(), &ChatForm::micMuteToggle, core, &Core::micMuteToggle); + connect(newfriend->getChatForm(), &ChatForm::volMuteToggle, core, &Core::volMuteToggle); connect(newfriend->getChatForm(), &ChatForm::aliasChanged, newfriend->getFriendWidget(), &FriendWidget::setAlias); connect(core, &Core::fileReceiveRequested, newfriend->getChatForm(), &ChatForm::onFileRecvRequest); connect(core, &Core::avInvite, newfriend->getChatForm(), &ChatForm::onAvInvite); @@ -651,11 +650,11 @@ void Widget::onFriendStatusChanged(int friendId, Status status) { if (f->getStatus() == Status::Offline) { - contactListWidget->moveWidget(f->getFriendWidget(), Status::Online, f->getEventFlag()); + contactListWidget->moveWidget(f->getFriendWidget(), Status::Online); } else if (status == Status::Offline) { - contactListWidget->moveWidget(f->getFriendWidget(), Status::Offline, f->getEventFlag()); + contactListWidget->moveWidget(f->getFriendWidget(), Status::Offline); } } @@ -999,8 +998,8 @@ Group *Widget::createGroup(int groupId) connect(newgroup->getGroupWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*)), this, SLOT(onChatroomWidgetClicked(GenericChatroomWidget*))); connect(newgroup->getGroupWidget(), SIGNAL(removeGroup(int)), this, SLOT(removeGroup(int))); connect(newgroup->getGroupWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*)), newgroup->getChatForm(), SLOT(focusInput())); - connect(newgroup->getChatForm(), SIGNAL(sendMessage(int,QString)), core, SLOT(sendGroupMessage(int,QString))); - connect(newgroup->getChatForm(), SIGNAL(sendAction(int,QString)), core, SLOT(sendGroupAction(int,QString))); + connect(newgroup->getChatForm(), &GroupChatForm::sendMessage, core, &Core::sendGroupMessage); + connect(newgroup->getChatForm(), &GroupChatForm::sendAction, core, &Core::sendGroupAction); connect(newgroup->getChatForm(), &GroupChatForm::groupTitleChanged, core, &Core::changeGroupTitle); return newgroup; } @@ -1139,7 +1138,7 @@ void Widget::setStatusBusy() Nexus::getCore()->setStatus(Status::Busy); } -void Widget::onMessageSendResult(int friendId, const QString& message, int messageId) +void Widget::onMessageSendResult(uint32_t friendId, const QString& message, int messageId) { Q_UNUSED(message) Q_UNUSED(messageId) diff --git a/src/widget/widget.h b/src/widget/widget.h index 001b55f2c..73e299d52 100644 --- a/src/widget/widget.h +++ b/src/widget/widget.h @@ -35,7 +35,7 @@ class MainWindow; class GenericChatroomWidget; class Group; -struct Friend; +class Friend; class QSplitter; class VideoSurface; class QMenu; @@ -104,6 +104,7 @@ public slots: void onFriendUsernameChanged(int friendId, const QString& username); void onFriendMessageReceived(int friendId, const QString& message, bool isAction); void onFriendRequestReceived(const QString& userId, const QString& message); + void onMessageSendResult(uint32_t friendId, const QString& message, int messageId); void onReceiptRecieved(int friendId, int receipt); void onEmptyGroupCreated(int groupId); void onGroupInviteReceived(int32_t friendId, uint8_t type, QByteArray invite); @@ -111,6 +112,7 @@ public slots: void onGroupNamelistChanged(int groupnumber, int peernumber, uint8_t change); void onGroupTitleChanged(int groupnumber, const QString& author, const QString& title); void onGroupPeerAudioPlaying(int groupnumber, int peernumber); + void onGroupSendResult(int groupId, const QString& message, int result); void playRingtone(); void onFriendTypingChanged(int friendId, bool isTyping); void nextContact(); @@ -140,8 +142,6 @@ private slots: void setStatusOnline(); void setStatusAway(); void setStatusBusy(); - void onMessageSendResult(int friendId, const QString& message, int messageId); - void onGroupSendResult(int groupId, const QString& message, int result); void onIconClick(QSystemTrayIcon::ActivationReason); void onUserAwayCheck(); void onEventIconTick(); From 33186e51dc845b4cf11bab12f649f0907f4a7424 Mon Sep 17 00:00:00 2001 From: Zetok Zalbavar Date: Mon, 20 Apr 2015 08:58:06 +0100 Subject: [PATCH 06/51] Some code style fixes --- src/core.cpp | 101 +++++++++++++++++++++++++++++------------ src/coreencryption.cpp | 10 +++- src/toxdns.cpp | 56 +++++++++++++++++------ 3 files changed, 123 insertions(+), 44 deletions(-) diff --git a/src/core.cpp b/src/core.cpp index 2269039e1..56c7341f4 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -172,6 +172,7 @@ void Core::make_tox(QByteArray savedata) toxOptions.proxy_type = TOX_PROXY_TYPE_SOCKS5; 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]; @@ -203,7 +204,9 @@ void Core::make_tox(QByteArray savedata) return; } else + { qWarning() << "Core failed to start with IPv6, falling back to IPv4. LAN discovery may not work properly."; + } } else if (toxOptions.proxy_type != TOX_PROXY_TYPE_NONE) { @@ -336,7 +339,9 @@ void Core::start() setAvatar(data); } else + { qDebug() << "Core: Error loading self avatar"; + } ready = true; @@ -367,7 +372,9 @@ void Core::process() #endif if (checkConnection()) + { tolerance = CORE_DISCONNECT_TOLERANCE; + } else if (!(--tolerance)) { bootstrapDht(); @@ -383,13 +390,16 @@ bool Core::checkConnection() //static int count = 0; bool toxConnected = tox_self_get_connection_status(tox) != TOX_CONNECTION_NONE; - if (toxConnected && !isConnected) { + if (toxConnected && !isConnected) + { qDebug() << "Core: Connected to DHT"; emit connected(); isConnected = true; //if (count) qDebug() << "Core: disconnect count:" << count; //count = 0; - } else if (!toxConnected && isConnected) { + } + else if (!toxConnected && isConnected) + { qDebug() << "Core: Disconnected to DHT"; emit disconnected(); isConnected = false; @@ -419,10 +429,14 @@ void Core::bootstrapDht() const Settings::DhtServer& dhtServer = dhtServerList[j % listSize]; if (tox_bootstrap(tox, dhtServer.address.toLatin1().data(), dhtServer.port, CUserId(dhtServer.userId).data(), nullptr) == 1) + { qDebug() << QString("Core: Bootstrapping from ")+dhtServer.name+QString(", addr ")+dhtServer.address.toLatin1().data() +QString(", port ")+QString().setNum(dhtServer.port); + } else + { qDebug() << "Core: Error bootstrapping from "+dhtServer.name; + } j++; i++; @@ -484,7 +498,8 @@ void Core::onConnectionStatusChanged(Tox*/* tox*/, uint32_t friendId, TOX_CONNEC { Status friendStatus = status ? Status::Online : Status::Offline; emit static_cast(core)->friendStatusChanged(friendId, friendStatus); - if (friendStatus == Status::Offline) { + if (friendStatus == Status::Offline) + { static_cast(core)->checkLastOnline(friendId); for (ToxFile& f : fileSendQueue) @@ -503,7 +518,9 @@ void Core::onConnectionStatusChanged(Tox*/* tox*/, uint32_t friendId, TOX_CONNEC emit static_cast(core)->fileTransferBrokenUnbroken(f, true); } } - } else { + } + else + { for (ToxFile& f : fileRecvQueue) { if (f.friendId == friendId && f.status == ToxFile::BROKEN) @@ -560,6 +577,7 @@ void Core::onGroupTitleChange(Tox*, int groupnumber, int peernumber, const uint8 QString author; if (peernumber >= 0) author = core->getGroupPeerName(groupnumber, peernumber); + emit core->groupTitleChanged(groupnumber, author, CString::toString(title, len)); } @@ -776,9 +794,12 @@ void Core::onReadReceiptCallback(Tox*, uint32_t friendnumber, uint32_t receipt, void Core::acceptFriendRequest(const QString& userId) { uint32_t friendId = tox_friend_add_norequest(tox, CUserId(userId).data(), nullptr); - if (friendId == UINT32_MAX) { + if (friendId == UINT32_MAX) + { emit failedToAddFriend(userId); - } else { + } + else + { saveConfiguration(); emit friendAdded(friendId, userId); } @@ -1066,9 +1087,13 @@ void Core::removeFriend(uint32_t friendId, bool fake) { if (!isReady() || fake) return; - if (tox_friend_delete(tox, friendId, nullptr) == false) { + + if (tox_friend_delete(tox, friendId, nullptr) == false) + { emit failedToRemoveFriend(friendId); - } else { + } + else + { saveConfiguration(); emit friendRemoved(friendId); } @@ -1078,6 +1103,7 @@ void Core::removeGroup(int groupId, bool fake) { if (!isReady() || fake) return; + tox_del_groupchat(tox, groupId); if (groupCalls[groupId].active) @@ -1099,9 +1125,12 @@ void Core::setUsername(const QString& username) { CString cUsername(username); - if (tox_self_set_name(tox, cUsername.data(), cUsername.size(), nullptr) == false) { + if (tox_self_set_name(tox, cUsername.data(), cUsername.size(), nullptr) == false) + { emit failedToSetUsername(username); - } else { + } + else + { emit usernameSet(username); saveConfiguration(); } @@ -1168,7 +1197,9 @@ void Core::setStatusMessage(const QString& message) if (tox_self_set_status_message(tox, cMessage.data(), cMessage.size(), nullptr) == false) { emit failedToSetStatusMessage(message); - } else { + } + else + { saveConfiguration(); emit statusMessageSet(message); } @@ -1177,7 +1208,8 @@ void Core::setStatusMessage(const QString& message) void Core::setStatus(Status status) { TOX_USER_STATUS userstatus; - switch (status) { + switch (status) + { case Status::Online: userstatus = TOX_USER_STATUS_NONE; break; @@ -1210,11 +1242,14 @@ QString Core::sanitize(QString name) QList banned = {'/', '\\', ':', '<', '>', '"', '|', '?', '*'}; for (QChar c : banned) name.replace(c, '_'); + // also remove leading and trailing periods if (name[0] == '.') name[0] = '_'; + if (name.endsWith('.')) name[name.length()-1] = '_'; + return name; } @@ -1226,18 +1261,21 @@ QByteArray Core::loadToxSave(QString path) QFile configurationFile(path); qDebug() << "Core::loadConfiguration: reading from " << path; - if (!configurationFile.exists()) { + if (!configurationFile.exists()) + { qWarning() << "The Tox configuration file was not found"; return data; } - if (!configurationFile.open(QIODevice::ReadOnly)) { + if (!configurationFile.open(QIODevice::ReadOnly)) + { qCritical() << "File " << path << " cannot be opened"; return data; } qint64 fileSize = configurationFile.size(); - if (fileSize > 0) { + if (fileSize > 0) + { data = configurationFile.readAll(); /* TODO: Clean this up int error = tox_load(tox, reinterpret_cast(data.data()), data.size()); @@ -1279,7 +1317,8 @@ void Core::saveConfiguration() QString dir = Settings::getSettingsDirPath(); QDir directory(dir); - if (!directory.exists() && !directory.mkpath(directory.absolutePath())) { + if (!directory.exists() && !directory.mkpath(directory.absolutePath())) + { qCritical() << "Error while creating directory " << dir; return; } @@ -1338,17 +1377,21 @@ void Core::switchConfiguration(const QString& profile) void Core::loadFriends() { const uint32_t friendCount = tox_self_get_friend_list_size(tox); - if (friendCount > 0) { + if (friendCount > 0) + { // assuming there are not that many friends to fill up the whole stack uint32_t *ids = new uint32_t[friendCount]; tox_self_get_friend_list(tox, ids); uint8_t clientId[TOX_PUBLIC_KEY_SIZE]; - for (int32_t i = 0; i < static_cast(friendCount); ++i) { - if (tox_friend_get_public_key(tox, ids[i], clientId, nullptr)) { + for (int32_t i = 0; i < static_cast(friendCount); ++i) + { + if (tox_friend_get_public_key(tox, ids[i], clientId, nullptr)) + { emit friendAdded(ids[i], CUserId::toString(clientId)); const size_t nameSize = tox_friend_get_name_size(tox, ids[i], nullptr); - if (nameSize != SIZE_MAX) { + if (nameSize != SIZE_MAX) + { uint8_t *name = new uint8_t[nameSize]; if (tox_friend_get_name(tox, ids[i], name, nullptr)) emit friendUsernameChanged(ids[i], CString::toString(name, nameSize)); @@ -1356,9 +1399,11 @@ void Core::loadFriends() } const size_t statusMessageSize = tox_friend_get_status_message_size(tox, ids[i], nullptr); - if (statusMessageSize != SIZE_MAX) { + if (statusMessageSize != SIZE_MAX) + { uint8_t *statusMessage = new uint8_t[statusMessageSize]; - if (tox_friend_get_status_message(tox, ids[i], statusMessage, nullptr)) { + if (tox_friend_get_status_message(tox, ids[i], statusMessage, nullptr)) + { emit friendStatusMessageChanged(ids[i], CString::toString(statusMessage, statusMessageSize)); } delete[] statusMessage; @@ -1374,9 +1419,8 @@ void Core::loadFriends() void Core::checkLastOnline(uint32_t friendId) { const uint64_t lastOnline = tox_friend_get_last_online(tox, friendId, nullptr); - if (lastOnline != UINT64_MAX) { + if (lastOnline != UINT64_MAX) emit friendLastSeenChanged(friendId, QDateTime::fromTime_t(lastOnline)); - } } int Core::getGroupNumberPeers(int groupId) const @@ -1433,6 +1477,7 @@ QList Core::getGroupPeerNames(int groupId) const } for (int i=0; i(data.data()), data.size(), pwsaltedkeys[passtype], encrypted, nullptr)) @@ -121,6 +122,7 @@ QByteArray Core::decryptData(const QByteArray& data, PasswordType passtype) { if (!pwsaltedkeys[passtype]) return QByteArray(); + int sz = data.size() - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; uint8_t decrypted[sz]; if (!tox_pass_key_decrypt(reinterpret_cast(data.data()), data.size(), @@ -237,10 +239,12 @@ void Core::checkEncryptedHistory() { if (!exists || HistoryKeeper::checkPassword()) return; + dialogtxt = tr("The chat history password failed. Please try another?", "used only when pw set before load() doesn't work"); } else dialogtxt = a; + dialogtxt += "\n" + c; if (pwsaltedkeys[ptMain]) @@ -287,7 +291,8 @@ void Core::saveConfiguration(const QString& path) } QSaveFile configurationFile(path); - if (!configurationFile.open(QIODevice::WriteOnly)) { + if (!configurationFile.open(QIODevice::WriteOnly)) + { qCritical() << "File " << path << " cannot be opened"; return; } @@ -304,7 +309,8 @@ void Core::saveConfiguration(const QString& path) else fileSize = tox_get_savedata_size(tox); - if (fileSize > 0 && fileSize <= std::numeric_limits::max()) { + if (fileSize > 0 && fileSize <= std::numeric_limits::max()) + { uint8_t *data = new uint8_t[fileSize]; if (encrypt) diff --git a/src/toxdns.cpp b/src/toxdns.cpp index ab08b8e2d..6d6b7ee3f 100644 --- a/src/toxdns.cpp +++ b/src/toxdns.cpp @@ -58,35 +58,45 @@ QByteArray ToxDNS::fetchLastTextRecord(const QString& record, bool silent) qApp->processEvents(); QThread::msleep(100); } - if (timeout >= 30) { + if (timeout >= 30) + { dns.abort(); if (!silent) showWarning(tr("The connection timed out","The DNS gives the Tox ID associated to toxme.se addresses")); + return result; } - if (dns.error() == QDnsLookup::NotFoundError) { + if (dns.error() == QDnsLookup::NotFoundError) + { if (!silent) showWarning(tr("This address does not exist","The DNS gives the Tox ID associated to toxme.se addresses")); + return result; } - else if (dns.error() != QDnsLookup::NoError) { + else if (dns.error() != QDnsLookup::NoError) + { if (!silent) showWarning(tr("Error while looking up DNS","The DNS gives the Tox ID associated to toxme.se addresses")); + return result; } const QList textRecords = dns.textRecords(); - if (textRecords.isEmpty()) { + if (textRecords.isEmpty()) + { if (!silent) showWarning(tr("No text record found", "Error with the DNS")); + return result; } const QList textRecordValues = textRecords.last().values(); - if (textRecordValues.length() != 1) { + if (textRecordValues.length() != 1) + { if (!silent) showWarning(tr("Unexpected number of values in text record", "Error with the DNS")); + return result; } @@ -104,7 +114,8 @@ QString ToxDNS::queryTox1(const QString& record, bool silent) // Check toxdns protocol version int verx = entry.indexOf("v="); - if (verx) { + if (verx) + { verx += 2; int verend = entry.indexOf(';', verx); if (verend) @@ -114,6 +125,7 @@ QString ToxDNS::queryTox1(const QString& record, bool silent) { if (!silent) showWarning(tr("The version of Tox DNS used by this server is not supported", "Error with the DNS")); + return toxId; } } @@ -121,23 +133,29 @@ QString ToxDNS::queryTox1(const QString& record, bool silent) // Get the tox id int idx = entry.indexOf("id="); - if (idx < 0) { + if (idx < 0) + { if (!silent) showWarning(tr("The DNS lookup does not contain any Tox ID", "Error with the DNS")); + return toxId; } idx += 3; - if (entry.length() < idx + static_cast(TOX_HEX_ID_LENGTH)) { + if (entry.length() < idx + static_cast(TOX_HEX_ID_LENGTH)) + { if (!silent) showWarning(tr("The DNS lookup does not contain a valid Tox ID", "Error with the DNS")); + return toxId; } toxId = entry.mid(idx, TOX_HEX_ID_LENGTH); - if (!ToxID::isToxId(toxId)) { + if (!ToxID::isToxId(toxId)) + { if (!silent) showWarning(tr("The DNS lookup does not contain a valid Tox ID", "Error with the DNS")); + return toxId; } @@ -178,7 +196,8 @@ QString ToxDNS::queryTox3(const tox3_server& server, const QString &record, bool // Check toxdns protocol version verx = entry.indexOf("v="); - if (verx!=-1) { + if (verx!=-1) + { verx += 2; int verend = entry.indexOf(';', verx); if (verend!=-1) @@ -194,7 +213,8 @@ QString ToxDNS::queryTox3(const tox3_server& server, const QString &record, bool // Get and decrypt the tox id idx = entry.indexOf("id="); - if (idx < 0) { + if (idx < 0) + { qWarning() << "queryTox3: Server "< Date: Mon, 20 Apr 2015 11:59:52 +0200 Subject: [PATCH 07/51] Properly initialize tox_options --- src/core.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core.cpp b/src/core.cpp index 2269039e1..b68edbea8 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -147,8 +147,10 @@ void Core::make_tox(QByteArray savedata) qWarning() << "Core starting with IPv6 disabled. LAN discovery may not work properly."; Tox_Options toxOptions; + tox_options_default(&toxOptions); toxOptions.ipv6_enabled = enableIPv6; toxOptions.udp_enabled = !forceTCP; + toxOptions.start_port = toxOptions.end_port = 0; // No proxy by default toxOptions.proxy_type = TOX_PROXY_TYPE_NONE; @@ -439,6 +441,7 @@ void Core::onFriendRequest(Tox*/* tox*/, const uint8_t* cUserId, void Core::onFriendMessage(Tox*/* tox*/, uint32_t friendId, TOX_MESSAGE_TYPE type, const uint8_t* cMessage, size_t cMessageSize, void* core) { + /// TODO: Emit action or message depending on type emit static_cast(core)->friendMessageReceived(friendId,CString::toString(cMessage, cMessageSize), false); } From 5df7d8a06c1df258d252a5d7d137c9972edfe83a Mon Sep 17 00:00:00 2001 From: tux3 Date: Thu, 23 Apr 2015 22:59:12 +0200 Subject: [PATCH 08/51] Port profile encryption support to new API Profile encryption should be fairly stable. History encryption was *NOT* tested yet and as such may not work, cause profile corruption, or invoke nasal daemons. --- src/core.cpp | 24 +++++++++--------- src/coreencryption.cpp | 55 +++++++++++++++++++++++------------------- src/misc/settings.cpp | 1 - 3 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/core.cpp b/src/core.cpp index fb454f7c3..8791d428e 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -52,7 +52,7 @@ QThread* Core::coreThread{nullptr}; #define MAX_GROUP_MESSAGE_LEN 1024 Core::Core(Camera* cam, QThread *CoreThread, QString loadPath) : - tox(nullptr), camera(cam), loadPath(loadPath), ready{false} + tox(nullptr), toxav(nullptr), camera(cam), loadPath(loadPath), ready{false} { qDebug() << "Core: loading Tox from" << loadPath; @@ -238,6 +238,13 @@ void Core::start() QByteArray savedata = loadToxSave(loadPath); + // Do we need to create a new save & profile? + if (savedata.isNull()) + { + qDebug() << "Save file not found, creating a new profile"; + Settings::getInstance().load(); + } + make_tox(savedata); qsrand(time(nullptr)); @@ -247,6 +254,9 @@ void Core::start() * Let's write something clear that doesn't rely on magic global state instead * We need to: 1) Find a qTox profile, create if needed 2) Find a tox save, decrypt/create if needed * Not sure about the order tho. Look into this. + * + * Okay we fixed encrypted profiles at least partially (needs testing wrt profile switching, corruption?) + * Need to make sure history encrypted and not is handled correctly if (true) { if (loadPath.isEmpty()) @@ -1280,14 +1290,7 @@ QByteArray Core::loadToxSave(QString path) if (fileSize > 0) { data = configurationFile.readAll(); - /* TODO: Clean this up - int error = tox_load(tox, reinterpret_cast(data.data()), data.size()); - if (error < 0) - { - qWarning() << "Core: tox_load failed with error "<< error; - } - else if (error == 1) // Encrypted data save - { + if (tox_is_data_encrypted((uint8_t*)data.data())) { if (!loadEncryptedSave(data)) { configurationFile.close(); @@ -1300,10 +1303,9 @@ QByteArray Core::loadToxSave(QString path) Settings::getInstance().switchProfile(profile); HistoryKeeper::resetInstance(); } - return false; + return QByteArray(); } } - */ } configurationFile.close(); diff --git a/src/coreencryption.cpp b/src/coreencryption.cpp index f62faa6d5..f6deef235 100644 --- a/src/coreencryption.cpp +++ b/src/coreencryption.cpp @@ -57,12 +57,12 @@ void Core::useOtherPassword(PasswordType type) PasswordType other = (type == ptMain) ? ptHistory : ptMain; - std::copy(pwsaltedkeys[other], pwsaltedkeys[other]+TOX_PASS_KEY_LENGTH, pwsaltedkeys[type]); + std::copy(pwsaltedkeys[other], pwsaltedkeys[other]+1, pwsaltedkeys[type]); } void Core::clearPassword(PasswordType passtype) { - delete[] pwsaltedkeys[passtype]; + delete pwsaltedkeys[passtype]; pwsaltedkeys[passtype] = nullptr; } @@ -72,12 +72,12 @@ void Core::saveCurrentInformation() if (pwsaltedkeys[ptMain]) { backupkeys[ptMain] = new TOX_PASS_KEY; - std::copy(pwsaltedkeys[ptMain], pwsaltedkeys[ptMain]+TOX_PASS_KEY_LENGTH, backupkeys[ptMain]); + std::copy(pwsaltedkeys[ptMain], pwsaltedkeys[ptMain]+1, backupkeys[ptMain]); } if (pwsaltedkeys[ptHistory]) { backupkeys[ptHistory] = new TOX_PASS_KEY; - std::copy(pwsaltedkeys[ptHistory], pwsaltedkeys[ptHistory]+TOX_PASS_KEY_LENGTH, backupkeys[ptHistory]); + std::copy(pwsaltedkeys[ptHistory], pwsaltedkeys[ptHistory]+1, backupkeys[ptHistory]); } backupProfile = new QString(Settings::getInstance().getCurrentProfile()); } @@ -168,11 +168,10 @@ QByteArray Core::getSaltFromFile(QString filename) bool Core::loadEncryptedSave(QByteArray& data) { - assert(0); - /* if (!Settings::getInstance().getEncryptTox()) GUI::showWarning(tr("Encryption error"), tr("The .tox file is encrypted, but encryption was not checked, continuing regardless.")); + size_t fileSize = data.size(); int error = -1; QString a(tr("Please enter the password for the %1 profile.", "used in load() when no pw is already set").arg(Settings::getInstance().getCurrentProfile())); QString b(tr("The previous password is incorrect; please try again:", "used on retries in load()")); @@ -180,12 +179,15 @@ bool Core::loadEncryptedSave(QByteArray& data) if (pwsaltedkeys[ptMain]) // password set, try it { - error = tox_encrypted_key_load(tox, reinterpret_cast(data.data()), data.size(), pwsaltedkeys[ptMain]); - if (!error) + QByteArray newData(fileSize-TOX_PASS_ENCRYPTION_EXTRA_LENGTH, 0); + if (tox_pass_key_decrypt((uint8_t*)data.data(), fileSize, pwsaltedkeys[ptMain], + (uint8_t*)newData.data(), nullptr)) { + data = newData; Settings::getInstance().setEncryptTox(true); return true; } + dialogtxt = tr("The profile password failed. Please try another?", "used only when pw set before load() doesn't work"); } else @@ -206,13 +208,17 @@ bool Core::loadEncryptedSave(QByteArray& data) else setPassword(pw, ptMain, salt); - error = tox_encrypted_key_load(tox, reinterpret_cast(data.data()), data.size(), pwsaltedkeys[ptMain]); + QByteArray newData(fileSize-TOX_PASS_ENCRYPTION_EXTRA_LENGTH, 0); + error = !tox_pass_key_decrypt((uint8_t*)data.data(), data.size(), pwsaltedkeys[ptMain], + (uint8_t*)newData.data(), nullptr); + if (!error) + data = newData; + dialogtxt = a + "\n" + b; } while (error != 0); Settings::getInstance().setEncryptTox(true); return true; - */ } void Core::checkEncryptedHistory() @@ -299,15 +305,8 @@ void Core::saveConfiguration(const QString& path) qDebug() << "Core: writing tox_save to " << path; - uint32_t fileSize; + uint32_t fileSize = tox_get_savedata_size(tox); bool encrypt = Settings::getInstance().getEncryptTox(); - if (encrypt) - { - qCritical() << "Encrypted saving not implemented!"; - exit(-1); - } - else - fileSize = tox_get_savedata_size(tox); if (fileSize > 0 && fileSize <= std::numeric_limits::max()) { @@ -324,16 +323,22 @@ void Core::saveConfiguration(const QString& path) } else { - qCritical() << "Encryption not implemented"; - exit(-1); - /* - int ret = tox_encrypted_key_save(tox, data, pwsaltedkeys[ptMain]); - if (ret == -1) + tox_get_savedata(tox, data); + uint8_t* newData = new uint8_t[fileSize+TOX_PASS_ENCRYPTION_EXTRA_LENGTH]; + if (tox_pass_key_encrypt(data, fileSize, pwsaltedkeys[ptMain], newData, nullptr)) { - qCritical() << "Core::saveConfiguration: encryption of save file failed!!!"; + delete[] data; + data = newData; + fileSize+=TOX_PASS_ENCRYPTION_EXTRA_LENGTH; + } + else + { + delete[] newData; + delete[] data; + qCritical() << "Core::saveConfiguration(QString): Encryption failed, couldn't save"; + configurationFile.cancelWriting(); return; } - */ } } else diff --git a/src/misc/settings.cpp b/src/misc/settings.cpp index 198befbc9..2f3ef8652 100644 --- a/src/misc/settings.cpp +++ b/src/misc/settings.cpp @@ -297,7 +297,6 @@ void Settings::load() loaded = true; - if (!currentProfile.isEmpty()) // new profile in Core::switchConfiguration { // load from a profile specific friend data list if possible QString tmp = dir.filePath(currentProfile + ".ini"); From 3bf338e9ffc9a4cea2eda9bddc1030a4325628e7 Mon Sep 17 00:00:00 2001 From: tux3 Date: Thu, 23 Apr 2015 23:01:12 +0200 Subject: [PATCH 09/51] Fix profile reloading during switch That'll get rid of the encryption warnings message boxes and per-user settings not reloading when switching between profiles --- src/misc/settings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/misc/settings.cpp b/src/misc/settings.cpp index 2f3ef8652..88cde4cce 100644 --- a/src/misc/settings.cpp +++ b/src/misc/settings.cpp @@ -66,6 +66,7 @@ void Settings::switchProfile(const QString& profile) // If this instance is not main instance previous save did not happen therefore // we manually set profile again and load profile settings setCurrentProfile(profile); + loaded = false; load(); } From e03d80392ad16fde915b9e4fe49f61e424380428 Mon Sep 17 00:00:00 2001 From: tux3 Date: Thu, 23 Apr 2015 23:42:50 +0200 Subject: [PATCH 10/51] Fix GUI refresh when creating new profile Previously the username/status, and the combobox in profileForm weren't refreshing themselves --- src/core.cpp | 23 +++++++++++++---------- src/widget/form/profileform.cpp | 1 + 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/core.cpp b/src/core.cpp index 8791d428e..fa25ca7fd 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -238,15 +238,17 @@ void Core::start() QByteArray savedata = loadToxSave(loadPath); + make_tox(savedata); + // Do we need to create a new save & profile? if (savedata.isNull()) { qDebug() << "Save file not found, creating a new profile"; Settings::getInstance().load(); + setStatusMessage(tr("Toxing on qTox")); + setUsername(tr("qTox User")); } - make_tox(savedata); - qsrand(time(nullptr)); /** TODO: Review this mess. Actually rewrite it all @@ -278,14 +280,6 @@ void Core::start() // loadPath is meaningless after this loadPath = ""; } - else // new ID - { - QString id = getSelfId().toString(); - if (!id.isEmpty()) - emit idSet(id); - setStatusMessage(tr("Toxing on qTox")); // this also solves the not updating issue - setUsername(tr("qTox User")); - } */ // set GUI with user and statusmsg @@ -357,6 +351,15 @@ void Core::start() ready = true; + // If we created a new profile earlier, + // now that we're ready save it and ONLY THEN broadcast the new ID. + // This is useful for e.g. the profileForm that searches for saves. + if (savedata.isNull()) + { + saveConfiguration(); + emit idSet(getSelfId().toString()); + } + process(); // starts its own timer } diff --git a/src/widget/form/profileform.cpp b/src/widget/form/profileform.cpp index 68c5bc06a..0e05d4d11 100644 --- a/src/widget/form/profileform.cpp +++ b/src/widget/form/profileform.cpp @@ -183,6 +183,7 @@ void ProfileForm::setToxId(const QString& id) qr = new QRWidget(); qr->setQRData("tox:"+id); bodyUI->qrCode->setPixmap(QPixmap::fromImage(qr->getImage()->scaledToWidth(150))); + refreshProfiles(); } void ProfileForm::onAvatarClicked() From fff2caa0e1a905b25fd72a3bed9bb75e336927e7 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 01:08:34 +0200 Subject: [PATCH 11/51] Fix Core::getSaltFromFile's error checking tox_get_salt now returns a bool, not an int. So any error condition has to be inveted to check for 0 instead of -1. --- src/coreencryption.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/coreencryption.cpp b/src/coreencryption.cpp index f6deef235..bd19eab76 100644 --- a/src/coreencryption.cpp +++ b/src/coreencryption.cpp @@ -154,8 +154,7 @@ QByteArray Core::getSaltFromFile(QString filename) file.close(); uint8_t *salt = new uint8_t[TOX_PASS_SALT_LENGTH]; - int err = tox_get_salt(reinterpret_cast(data.data()), salt); - if (err) + if (!tox_get_salt(reinterpret_cast(data.data()), salt)) { qWarning() << "Core: can't get salt from" << filename << "header"; return QByteArray(); From 4fc6632d789d321b7b49058bfacd4dc7856bc149 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 01:10:42 +0200 Subject: [PATCH 12/51] Fix history-destroying use after free in Core::getSaltFromFile We returned a shallow copy of the delete[]'d salt buffer As a result the history consistently failed to decrypt and was removed as corrupted. This is now fixed. --- src/coreencryption.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreencryption.cpp b/src/coreencryption.cpp index bd19eab76..b71dd9478 100644 --- a/src/coreencryption.cpp +++ b/src/coreencryption.cpp @@ -160,7 +160,7 @@ QByteArray Core::getSaltFromFile(QString filename) return QByteArray(); } - QByteArray res = QByteArray::fromRawData(reinterpret_cast(salt), TOX_PASS_SALT_LENGTH); + QByteArray res(reinterpret_cast(salt), TOX_PASS_SALT_LENGTH); delete[] salt; return res; } From a70721818e0f236de450c49167d23066812955d1 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 01:15:09 +0200 Subject: [PATCH 13/51] Cleanup old commented-out code --- src/core.cpp | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/core.cpp b/src/core.cpp index fa25ca7fd..51021cfd3 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -251,37 +251,6 @@ void Core::start() qsrand(time(nullptr)); - /** TODO: Review this mess. Actually rewrite it all - * I have no idea what the whole fooling around with loadPath bussiness means anymore. - * Let's write something clear that doesn't rely on magic global state instead - * We need to: 1) Find a qTox profile, create if needed 2) Find a tox save, decrypt/create if needed - * Not sure about the order tho. Look into this. - * - * Okay we fixed encrypted profiles at least partially (needs testing wrt profile switching, corruption?) - * Need to make sure history encrypted and not is handled correctly - if (true) - { - if (loadPath.isEmpty()) - { - QString profile; - if ((profile = loadOldInformation()).isEmpty()) - { - qCritical() << "Core: loadConfiguration failed, exiting now"; - emit failedToStart(); - return; - } - else - { - loadPath = QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT); - Settings::getInstance().switchProfile(profile); - HistoryKeeper::resetInstance(); // I'm not actually sure if this is necessary - } - } - // loadPath is meaningless after this - loadPath = ""; - } - */ - // set GUI with user and statusmsg QString name = getUsername(); if (!name.isEmpty()) From e4859efe18644ea56faeb793cea462885f8e609b Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 02:32:09 +0200 Subject: [PATCH 14/51] Refactor Core Refactor Core's file transfer callbacks into their CoreFile class and files Move all core*.{h|cpp} into a core/ folder --- qtox.pro | 23 +- src/audio.cpp | 2 +- src/chatlog/chatmessage.h | 2 +- src/chatlog/content/filetransferwidget.cpp | 2 +- src/chatlog/content/filetransferwidget.h | 4 +- src/{ => core}/core.cpp | 323 +-------------------- src/{ => core}/core.h | 43 ++- src/{ => core}/coreav.cpp | 26 +- src/{ => core}/coreav.h | 2 +- src/{ => core}/coredefines.h | 0 src/{ => core}/coreencryption.cpp | 4 +- src/core/corefile.cpp | 26 ++ src/core/corefile.h | 28 ++ src/{ => core}/corestructs.cpp | 4 +- src/{ => core}/corestructs.h | 0 src/friend.cpp | 2 +- src/friend.h | 2 +- src/group.cpp | 2 +- src/historykeeper.cpp | 2 +- src/misc/db/encrypteddb.cpp | 2 +- src/misc/serialize.cpp | 10 +- src/misc/settings.cpp | 4 +- src/nexus.cpp | 2 +- src/offlinemsgengine.cpp | 2 +- src/toxdns.h | 2 +- src/toxme.cpp | 2 +- src/toxme.h | 2 +- src/widget/androidgui.cpp | 2 +- src/widget/androidgui.h | 2 +- src/widget/form/addfriendform.cpp | 2 +- src/widget/form/chatform.cpp | 2 +- src/widget/form/chatform.h | 2 +- src/widget/form/genericchatform.cpp | 2 +- src/widget/form/genericchatform.h | 2 +- src/widget/form/groupchatform.cpp | 2 +- src/widget/form/profileform.cpp | 2 +- src/widget/form/profileform.h | 2 +- src/widget/form/settings/generalform.cpp | 2 +- src/widget/form/settings/privacyform.cpp | 2 +- src/widget/form/tabcompleter.cpp | 2 +- src/widget/friendlistwidget.h | 2 +- src/widget/friendwidget.cpp | 2 +- src/widget/groupwidget.cpp | 2 +- src/widget/netcamview.cpp | 2 +- src/widget/toxsave.cpp | 2 +- src/widget/toxuri.cpp | 2 +- src/widget/widget.cpp | 2 +- src/widget/widget.h | 2 +- 48 files changed, 161 insertions(+), 404 deletions(-) rename src/{ => core}/core.cpp (78%) rename src/{ => core}/core.h (89%) rename src/{ => core}/coreav.cpp (96%) rename src/{ => core}/coreav.h (95%) rename src/{ => core}/coredefines.h (100%) rename src/{ => core}/coreencryption.cpp (99%) create mode 100644 src/core/corefile.cpp create mode 100644 src/core/corefile.h rename src/{ => core}/corestructs.cpp (96%) rename src/{ => core}/corestructs.h (100%) diff --git a/qtox.pro b/qtox.pro index a41ba5209..51506030d 100644 --- a/qtox.pro +++ b/qtox.pro @@ -409,10 +409,6 @@ contains(ENABLE_SYSTRAY_GTK_BACKEND, NO) { SOURCES += \ src/audio.cpp \ - src/core.cpp \ - src/coreav.cpp \ - src/coreencryption.cpp \ - src/corestructs.cpp \ src/historykeeper.cpp \ src/main.cpp \ src/nexus.cpp \ @@ -428,14 +424,20 @@ SOURCES += \ src/video/videoframe.cpp \ src/widget/gui.cpp \ src/toxme.cpp \ - src/misc/qrwidget.cpp + src/misc/qrwidget.cpp \ + src/core/core.cpp \ + src/core/coreav.cpp \ + src/core/coreencryption.cpp \ + src/core/corefile.cpp \ + src/core/corestructs.cpp \ HEADERS += \ src/audio.h \ - src/core.h \ - src/corestructs.h \ - src/coredefines.h \ - src/coreav.h \ + src/core/core.h \ + src/core/coreav.h \ + src/core/coredefines.h \ + src/core/corefile.h \ + src/core/corestructs.h \ src/historykeeper.h \ src/nexus.h \ src/misc/cdata.h \ @@ -448,6 +450,7 @@ HEADERS += \ src/video/cameraworker.h \ src/video/videoframe.h \ src/video/videosource.h \ + src/video/netvideosource.h \ src/widget/gui.h \ src/toxme.h \ - src/misc/qrwidget.h + src/misc/qrwidget.h \ diff --git a/src/audio.cpp b/src/audio.cpp index 697a71e73..47b338218 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -24,7 +24,7 @@ #define FIX_SND_PCM_PREPARE_BUG 0 #include "audio.h" -#include "src/core.h" +#include "src/core/core.h" #include #include diff --git a/src/chatlog/chatmessage.h b/src/chatlog/chatmessage.h index 8f6b58a29..07eb61a70 100644 --- a/src/chatlog/chatmessage.h +++ b/src/chatlog/chatmessage.h @@ -18,7 +18,7 @@ #define CHATMESSAGE_H #include "chatline.h" -#include "src/corestructs.h" +#include "src/core/corestructs.h" #include class QGraphicsScene; diff --git a/src/chatlog/content/filetransferwidget.cpp b/src/chatlog/content/filetransferwidget.cpp index 3347bcc80..466138dbf 100644 --- a/src/chatlog/content/filetransferwidget.cpp +++ b/src/chatlog/content/filetransferwidget.cpp @@ -18,7 +18,7 @@ #include "ui_filetransferwidget.h" #include "src/nexus.h" -#include "src/core.h" +#include "src/core/core.h" #include "src/misc/style.h" #include "src/widget/widget.h" diff --git a/src/chatlog/content/filetransferwidget.h b/src/chatlog/content/filetransferwidget.h index 3a84f14e4..5a5b8ef6f 100644 --- a/src/chatlog/content/filetransferwidget.h +++ b/src/chatlog/content/filetransferwidget.h @@ -20,8 +20,8 @@ #include #include -#include "../chatlinecontent.h" -#include "../../corestructs.h" +#include "src/chatlog/chatlinecontent.h" +#include "src/core/corestructs.h" namespace Ui { diff --git a/src/core.cpp b/src/core/core.cpp similarity index 78% rename from src/core.cpp rename to src/core/core.cpp index 51021cfd3..c13da28fe 100644 --- a/src/core.cpp +++ b/src/core/core.cpp @@ -15,13 +15,14 @@ */ #include "core.h" -#include "nexus.h" -#include "misc/cdata.h" -#include "misc/cstring.h" -#include "misc/settings.h" -#include "widget/gui.h" -#include "historykeeper.h" +#include "src/nexus.h" +#include "src/misc/cdata.h" +#include "src/misc/cstring.h" +#include "src/misc/settings.h" +#include "src/widget/gui.h" +#include "src/historykeeper.h" #include "src/audio.h" +#include "corefile.h" #include @@ -70,7 +71,6 @@ Core::Core(Camera* cam, QThread *CoreThread, QString loadPath) : connect(toxTimer, &QTimer::timeout, this, &Core::process); //connect(fileTimer, &QTimer::timeout, this, &Core::fileHeartbeat); connect(&Settings::getInstance(), &Settings::dhtServerListChanged, this, &Core::process); - connect(this, SIGNAL(fileTransferFinished(ToxFile)), this, SLOT(onFileTransferFinished(ToxFile))); for (int i=0; igroupTitleChanged(groupnumber, author, CString::toString(title, len)); } -void Core::onFileSendRequestCallback(Tox*, uint32_t friendnumber, uint8_t filenumber, uint64_t filesize, - const uint8_t *filename, uint16_t filename_length, void *core) -{ - qDebug() << QString("Core: Received file request %1 with friend %2").arg(filenumber).arg(friendnumber); - - ToxFile file{filenumber, friendnumber, - CString::toString(filename,filename_length).toUtf8(), "", ToxFile::RECEIVING}; - file.filesize = filesize; - fileRecvQueue.append(file); - emit static_cast(core)->fileReceiveRequested(fileRecvQueue.last()); -} -void Core::onFileControlCallback(Tox* tox, uint32_t friendnumber, uint8_t receive_send, uint8_t filenumber, - uint8_t control_type, const uint8_t* data, uint16_t length, void *core) -{ - ToxFile* file{nullptr}; - if (receive_send == 1) - { - for (ToxFile& f : fileSendQueue) - { - if (f.fileNum == filenumber && f.friendId == friendnumber) - { - file = &f; - break; - } - } - } - else - { - for (ToxFile& f : fileRecvQueue) - { - if (f.fileNum == filenumber && f.friendId == friendnumber) - { - file = &f; - break; - } - } - } - if (!file) - { - qWarning("Core::onFileControlCallback: No such file in queue"); - return; - } - if (receive_send == 1 && control_type == TOX_FILE_CONTROL_RESUME) - { - file->status = ToxFile::TRANSMITTING; - emit static_cast(core)->fileTransferAccepted(*file); - qDebug() << "Core: File control callback, file accepted"; - file->sendTimer = new QTimer(static_cast(core)); - connect(file->sendTimer, &QTimer::timeout, std::bind(sendAllFileData,static_cast(core), file)); - file->sendTimer->setSingleShot(true); - file->sendTimer->start(TOX_FILE_INTERVAL); - } - else if (receive_send == 1 && control_type == TOX_FILE_CONTROL_CANCEL) - { - qDebug() << QString("Core::onFileControlCallback: Transfer of file %1 cancelled by friend %2") - .arg(file->fileNum).arg(file->friendId); - file->status = ToxFile::STOPPED; - emit static_cast(core)->fileTransferCancelled(*file); - // Wait for sendAllFileData to return before deleting the ToxFile, we MUST ensure this or we'll use after free - if (file->sendTimer) - { - QThread::msleep(1); - qApp->processEvents(); - if (file->sendTimer) - { - delete file->sendTimer; - file->sendTimer = nullptr; - } - } - removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); - } - else if (receive_send == 1 && false /* && control_type == TOX_FILECONTROL_FINISHED*/ ) ///TODO: FIXME: Detect finished transfers - { - qDebug() << QString("Core::onFileControlCallback: Transfer of file %1 to friend %2 is complete") - .arg(file->fileNum).arg(file->friendId); - file->status = ToxFile::STOPPED; - emit static_cast(core)->fileTransferFinished(*file); - removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); - } - else if (receive_send == 0 && control_type == TOX_FILE_CONTROL_CANCEL) - { - qDebug() << QString("Core::onFileControlCallback: Transfer of file %1 cancelled by friend %2") - .arg(file->fileNum).arg(file->friendId); - file->status = ToxFile::STOPPED; - emit static_cast(core)->fileTransferCancelled(*file); - removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); - } - else if (receive_send == 0 && false /* && control_type == TOX_FILECONTROL_FINISHED*/ ) ///TODO: FIXME: Detect finished transfers - { - qDebug() << QString("Core::onFileControlCallback: Reception of file %1 from %2 finished") - .arg(file->fileNum).arg(file->friendId); - file->status = ToxFile::STOPPED; - emit static_cast(core)->fileTransferFinished(*file); - // confirm receive is complete - ///tox_file_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_FINISHED, nullptr, 0); - removeFileFromQueue((bool)receive_send, file->friendId, file->fileNum); - } - else if (receive_send == 0 && control_type == TOX_FILE_CONTROL_RESUME) - { - if (file->status == ToxFile::BROKEN) - { - emit static_cast(core)->fileTransferBrokenUnbroken(*file, false); - file->status = ToxFile::TRANSMITTING; - } - emit static_cast(core)->fileTransferRemotePausedUnpaused(*file, false); - } - else if ((receive_send == 0 || receive_send == 1) && control_type == TOX_FILE_CONTROL_PAUSE) - { - emit static_cast(core)->fileTransferRemotePausedUnpaused(*file, true); - } - else if (receive_send == 1 && control_type == TOX_FILE_CONTROL_RESUME) - { - if (length != sizeof(uint64_t)) - return; - - qDebug() << "Core::onFileControlCallback: TOX_FILECONTROL_RESUME_BROKEN"; - - uint64_t resumePos = *reinterpret_cast(data); - - if (resumePos >= (unsigned)file->filesize) - { - qWarning() << "Core::onFileControlCallback: invalid resume position"; - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); // don't sure about it - return; - } - - file->status = ToxFile::TRANSMITTING; - emit static_cast(core)->fileTransferBrokenUnbroken(*file, false); - - file->bytesSent = resumePos; - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); - } - else - { - qDebug() << QString("Core: File control callback, receive_send=%1, control_type=%2") - .arg(receive_send).arg(control_type); - } -} - -void Core::onFileDataCallback(Tox*, uint32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *core) -{ - ToxFile* file{nullptr}; - for (ToxFile& f : fileRecvQueue) - { - if (f.fileNum == filenumber && f.friendId == friendnumber) - { - file = &f; - break; - } - } - if (!file) - { - qWarning("Core::onFileDataCallback: No such file in queue"); - return; - } - - file->file->write((char*)data,length); - file->bytesSent += length; - //qDebug() << QString("Core::onFileDataCallback: received %1/%2 bytes").arg(file->bytesSent).arg(file->filesize); - emit static_cast(core)->fileTransferInfo(*file); -} - -void Core::onAvatarInfoCallback(Tox*, uint32_t friendnumber, uint8_t format, - uint8_t* hash, void* _core) -{ - assert(0); - /* TODO: Address this avatar function - Core* core = static_cast(_core); - - if (format == TOX_AVATAR_FORMAT_NONE) - { - //qDebug() << "Core: Got null avatar info from" << core->getFriendUsername(friendnumber); - emit core->friendAvatarRemoved(friendnumber); - QFile::remove(QDir(Settings::getSettingsDirPath()).filePath("avatars/"+core->getFriendAddress(friendnumber).left(64)+".png")); - QFile::remove(QDir(Settings::getSettingsDirPath()).filePath("avatars/"+core->getFriendAddress(friendnumber).left(64)+".hash")); - } - else - { - QByteArray oldHash = Settings::getInstance().getAvatarHash(core->getFriendAddress(friendnumber)); - if (QByteArray((char*)hash, TOX_HASH_LENGTH) != oldHash) - // comparison failed miserably if I didn't convert hash to QByteArray - { - qDebug() << "Core: Got new avatar info from" << core->getFriendUsername(friendnumber); - tox_request_avatar_data(core->tox, friendnumber); - } - //else - // qDebug() << "Core: Got same avatar info from" << core->getFriendUsername(friendnumber); - } - */ -} - -void Core::onAvatarDataCallback(Tox*, uint32_t friendnumber, uint8_t, - uint8_t *hash, uint8_t *data, uint32_t datalen, void *core) -{ - QPixmap pic; - pic.loadFromData((uchar*)data, datalen); - if (!pic.isNull()) - { - qDebug() << "Core: Got avatar data from" << static_cast(core)->getFriendUsername(friendnumber); - Settings::getInstance().saveAvatar(pic, static_cast(core)->getFriendAddress(friendnumber)); - Settings::getInstance().saveAvatarHash(QByteArray((char*)hash, TOX_HASH_LENGTH), static_cast(core)->getFriendAddress(friendnumber)); - emit static_cast(core)->friendAvatarChanged(friendnumber, pic); - } -} - void Core::onReadReceiptCallback(Tox*, uint32_t friendnumber, uint32_t receipt, void *core) { emit static_cast(core)->receiptRecieved(friendnumber, receipt); @@ -1213,14 +1007,6 @@ void Core::setStatus(Status status) emit statusSet(status); } -void Core::onFileTransferFinished(ToxFile file) -{ - if (file.direction == file.SENDING) - emit fileUploadFinished(file.filePath); - else - emit fileDownloadFinished(file.filePath); -} - QString Core::sanitize(QString name) { // these are pretty much Windows banned filename characters @@ -1520,91 +1306,6 @@ void Core::removeFileFromQueue(bool sendQueue, uint32_t friendId, uint32_t fileI qWarning() << "Core::removeFileFromQueue: No such file in queue"; } -void Core::sendAllFileData(Core *core, ToxFile* file) -{ - assert(0); - /** TODO: Reimplement file transfers using tox_file_chunk_request_cb - if (file->status == ToxFile::PAUSED) - { - file->sendTimer->start(5+TOX_FILE_INTERVAL); - return; - } - else if (file->status == ToxFile::STOPPED) - { - qWarning("Core::sendAllFileData: File is stopped"); - file->sendTimer->disconnect(); - delete file->sendTimer; - file->sendTimer = nullptr; - return; - } - emit core->fileTransferInfo(*file); -// qApp->processEvents(); - long long chunkSize = tox_file_data_size(core->tox, file->friendId); - if (chunkSize == -1) - { - qWarning("Core::fileHeartbeat: Error getting preffered chunk size, aborting file send"); - file->status = ToxFile::STOPPED; - emit core->fileTransferCancelled(*file); - tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); - removeFileFromQueue(true, file->friendId, file->fileNum); - return; - } - //qDebug() << "chunkSize: " << chunkSize; - chunkSize = std::min(chunkSize, file->filesize); - uint8_t* data = new uint8_t[chunkSize]; - file->file->seek(file->bytesSent); - int readSize = file->file->read((char*)data, chunkSize); - if (readSize == -1) - { - qWarning() << QString("Core::sendAllFileData: Error reading from file: %1").arg(file->file->errorString()); - delete[] data; - file->status = ToxFile::STOPPED; - emit core->fileTransferCancelled(*file); - tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); - removeFileFromQueue(true, file->friendId, file->fileNum); - return; - } - else if (readSize == 0) - { - qWarning() << QString("Core::sendAllFileData: Nothing to read from file: %1").arg(file->file->errorString()); - delete[] data; - file->status = ToxFile::STOPPED; - emit core->fileTransferCancelled(*file); - tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); - removeFileFromQueue(true, file->friendId, file->fileNum); - return; - } - if (tox_file_send_data(core->tox, file->friendId, file->fileNum, data, readSize) == -1) - { - //qWarning("Core::fileHeartbeat: Error sending data chunk"); - //core->process(); - delete[] data; - //QThread::msleep(1); - file->sendTimer->start(1+TOX_FILE_INTERVAL); - return; - } - delete[] data; - file->bytesSent += readSize; - //qDebug() << QString("Core::fileHeartbeat: sent %1/%2 bytes").arg(file->bytesSent).arg(file->fileData.size()); - - if (file->bytesSent < file->filesize) - { - file->sendTimer->start(TOX_FILE_INTERVAL); - return; - } - else - { - //qDebug("Core: File transfer finished"); - file->sendTimer->disconnect(); - delete file->sendTimer; - file->sendTimer = nullptr; - /// TODO: Review this, we can't send finished messages anymore, but maybe we don't need to - ///tox_file_control(core->tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_FINISHED, nullptr, 0); - //emit core->fileTransferFinished(*file); - } - */ -} - void Core::groupInviteFriend(uint32_t friendId, int groupId) { tox_invite_friend(tox, friendId, groupId); diff --git a/src/core.h b/src/core/core.h similarity index 89% rename from src/core.h rename to src/core/core.h index e1217d364..e01b7d5ae 100644 --- a/src/core.h +++ b/src/core/core.h @@ -226,25 +226,26 @@ signals: void videoFrameReceived(vpx_image* frame); private: - static void onFriendRequest(Tox* tox, const uint8_t* cUserId, const uint8_t* cMessage, size_t cMessageSize, void* core); - static void onFriendMessage(Tox* tox, uint32_t friendId, TOX_MESSAGE_TYPE type, const uint8_t* cMessage, size_t cMessageSize, void* core); - static void onFriendNameChange(Tox* tox, uint32_t friendId, const uint8_t* cName, size_t cNameSize, void* core); + static void onFriendRequest(Tox* tox, const uint8_t* cUserId, const uint8_t* cMessage, + size_t cMessageSize, void* core); + static void onFriendMessage(Tox* tox, uint32_t friendId, TOX_MESSAGE_TYPE type, + const uint8_t* cMessage, size_t cMessageSize, void* core); + static void onFriendNameChange(Tox* tox, uint32_t friendId, const uint8_t* cName, + size_t cNameSize, void* core); static void onFriendTypingChange(Tox* tox, uint32_t friendId, bool isTyping, void* core); - static void onStatusMessageChanged(Tox* tox, uint32_t friendId, const uint8_t* cMessage, size_t cMessageSize, void* core); + static void onStatusMessageChanged(Tox* tox, uint32_t friendId, const uint8_t* cMessage, + size_t cMessageSize, void* core); static void onUserStatusChanged(Tox* tox, uint32_t friendId, TOX_USER_STATUS userstatus, void* core); static void onConnectionStatusChanged(Tox* tox, uint32_t friendId, TOX_CONNECTION status, void* core); - static void onGroupAction(Tox* tox, int groupnumber, int peernumber, const uint8_t * action, uint16_t length, void* core); - static void onGroupInvite(Tox *tox, int32_t friendNumber, uint8_t type, const uint8_t *data, uint16_t length, void *userdata); - static void onGroupMessage(Tox *tox, int groupnumber, int friendgroupnumber, const uint8_t * message, uint16_t length, void *userdata); - static void onGroupNamelistChange(Tox *tox, int groupnumber, int peernumber, uint8_t change, void *userdata); - static void onGroupTitleChange(Tox*, int groupnumber, int peernumber, const uint8_t* title, uint8_t len, void* _core); - static void onFileSendRequestCallback(Tox *tox, uint32_t friendnumber, uint8_t filenumber, uint64_t filesize, - const uint8_t *filename, uint16_t filename_length, void *userdata); - static void onFileControlCallback(Tox *tox, uint32_t friendnumber, uint8_t receive_send, uint8_t filenumber, - uint8_t control_type, const uint8_t *data, uint16_t length, void *core); - static void onFileDataCallback(Tox *tox, uint32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length, void *userdata); - static void onAvatarInfoCallback(Tox* tox, uint32_t friendnumber, uint8_t format, uint8_t *hash, void *userdata); - static void onAvatarDataCallback(Tox* tox, uint32_t friendnumber, uint8_t format, uint8_t *hash, uint8_t *data, uint32_t datalen, void *userdata); + static void onGroupAction(Tox* tox, int groupnumber, int peernumber, const uint8_t * action, + uint16_t length, void* core); + static void onGroupInvite(Tox *tox, int32_t friendNumber, uint8_t type, const uint8_t *data, + uint16_t length, void *userdata); + static void onGroupMessage(Tox *tox, int groupnumber, int friendgroupnumber, + const uint8_t * message, uint16_t length, void *userdata); + static void onGroupNamelistChange(Tox *tox, int groupId, int peerId, uint8_t change, void *core); + static void onGroupTitleChange(Tox*, int groupnumber, int peernumber, + const uint8_t* title, uint8_t len, void* _core); static void onReadReceiptCallback(Tox *tox, uint32_t friendnumber, uint32_t receipt, void *core); static void onAvInvite(void* toxav, int32_t call_index, void* core); @@ -261,9 +262,11 @@ private: static void prepareCall(uint32_t friendId, int callId, ToxAv *toxav, bool videoEnabled); static void cleanupCall(int callId); - static void playCallAudio(void *toxav, int32_t callId, const int16_t *data, uint16_t samples, void *user_data); // Callback + static void playCallAudio(void *toxav, int32_t callId, const int16_t *data, + uint16_t samples, void *user_data); // Callback static void sendCallAudio(int callId, ToxAv* toxav); - static void playAudioBuffer(ALuint alSource, const int16_t *data, int samples, unsigned channels, int sampleRate); + static void playAudioBuffer(ALuint alSource, const int16_t *data, int samples, + unsigned channels, int sampleRate); static void playCallVideo(void *toxav, int32_t callId, const vpx_image_t* img, void *user_data); void sendCallVideo(int callId); @@ -275,16 +278,12 @@ private: void make_tox(QByteArray savedata); void loadFriends(); - static void sendAllFileData(Core* core, ToxFile* file); static void removeFileFromQueue(bool sendQueue, uint32_t friendId, uint32_t fileId); void checkLastOnline(uint32_t friendId); void deadifyTox(); -private slots: - void onFileTransferFinished(ToxFile file); - private: Tox* tox; ToxAv* toxav; diff --git a/src/coreav.cpp b/src/core/coreav.cpp similarity index 96% rename from src/coreav.cpp rename to src/core/coreav.cpp index bdd022b00..9e44457b9 100644 --- a/src/coreav.cpp +++ b/src/core/coreav.cpp @@ -15,12 +15,12 @@ */ #include "core.h" -#include "video/camera.h" -#include "audio.h" +#include "src/video/camera.h" +#include "src/audio.h" #ifdef QTOX_FILTER_AUDIO -#include "audiofilterer.h" +#include "src/audiofilterer.h" #endif -#include "misc/settings.h" +#include "src/misc/settings.h" #include #include @@ -122,7 +122,7 @@ fail: // Centralized error handling void Core::answerCall(int32_t callId) { - uint32_t friendId = toxav_get_peer_id(toxav, callId, 0); + int friendId = toxav_get_peer_id(toxav, callId, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV answer peer ID"; @@ -354,7 +354,7 @@ void Core::onAvCancel(void* _toxav, int32_t callId, void* core) { ToxAv* toxav = static_cast(_toxav); - uint32_t friendId = toxav_get_peer_id(toxav, callId, 0); + int friendId = toxav_get_peer_id(toxav, callId, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV cancel"; @@ -379,7 +379,7 @@ void Core::onAvCancel(void* _toxav, int32_t callId, void* core) void Core::onAvReject(void* _toxav, int32_t callId, void* core) { ToxAv* toxav = static_cast(_toxav); - uint32_t friendId = toxav_get_peer_id(toxav, callId, 0); + int friendId = toxav_get_peer_id(toxav, callId, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV reject"; @@ -395,7 +395,7 @@ void Core::onAvEnd(void* _toxav, int32_t call_index, void* core) { ToxAv* toxav = static_cast(_toxav); - uint32_t friendId = toxav_get_peer_id(toxav, call_index, 0); + int friendId = toxav_get_peer_id(toxav, call_index, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV end"; @@ -412,7 +412,7 @@ void Core::onAvRinging(void* _toxav, int32_t call_index, void* core) { ToxAv* toxav = static_cast(_toxav); - uint32_t friendId = toxav_get_peer_id(toxav, call_index, 0); + int friendId = toxav_get_peer_id(toxav, call_index, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV ringing"; @@ -435,7 +435,7 @@ void Core::onAvRequestTimeout(void* _toxav, int32_t call_index, void* core) { ToxAv* toxav = static_cast(_toxav); - uint32_t friendId = toxav_get_peer_id(toxav, call_index, 0); + int friendId = toxav_get_peer_id(toxav, call_index, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV request timeout"; @@ -452,7 +452,7 @@ void Core::onAvPeerTimeout(void* _toxav, int32_t call_index, void* core) { ToxAv* toxav = static_cast(_toxav); - uint32_t friendId = toxav_get_peer_id(toxav, call_index, 0); + int friendId = toxav_get_peer_id(toxav, call_index, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV peer timeout"; @@ -470,7 +470,7 @@ void Core::onAvInvite(void* _toxav, int32_t call_index, void* core) { ToxAv* toxav = static_cast(_toxav); - uint32_t friendId = toxav_get_peer_id(toxav, call_index, 0); + int friendId = toxav_get_peer_id(toxav, call_index, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV invite"; @@ -504,7 +504,7 @@ void Core::onAvStart(void* _toxav, int32_t call_index, void* core) { ToxAv* toxav = static_cast(_toxav); - uint32_t friendId = toxav_get_peer_id(toxav, call_index, 0); + int friendId = toxav_get_peer_id(toxav, call_index, 0); if (friendId < 0) { qWarning() << "Core: Received invalid AV start"; diff --git a/src/coreav.h b/src/core/coreav.h similarity index 95% rename from src/coreav.h rename to src/core/coreav.h index 48c514808..6b81b29f1 100644 --- a/src/coreav.h +++ b/src/core/coreav.h @@ -3,7 +3,7 @@ #include #include -#include "video/netvideosource.h" +#include "src/video/netvideosource.h" #if defined(__APPLE__) && defined(__MACH__) #include diff --git a/src/coredefines.h b/src/core/coredefines.h similarity index 100% rename from src/coredefines.h rename to src/core/coredefines.h diff --git a/src/coreencryption.cpp b/src/core/coreencryption.cpp similarity index 99% rename from src/coreencryption.cpp rename to src/core/coreencryption.cpp index b71dd9478..2df15fe57 100644 --- a/src/coreencryption.cpp +++ b/src/core/coreencryption.cpp @@ -21,8 +21,8 @@ #include "core.h" #include "src/widget/gui.h" #include "src/misc/settings.h" -#include "misc/cstring.h" -#include "historykeeper.h" +#include "src/misc/cstring.h" +#include "src/historykeeper.h" #include #include #include diff --git a/src/core/corefile.cpp b/src/core/corefile.cpp new file mode 100644 index 000000000..d636d25c7 --- /dev/null +++ b/src/core/corefile.cpp @@ -0,0 +1,26 @@ +#include "corefile.h" +#include + +void CoreFile::onFileReceiveCallback(Tox*, uint32_t friendId, uint32_t fileId, uint32_t kind, + uint64_t filesize, const uint8_t *fname, size_t fnameLen, void *core) +{ + qDebug() << QString("Core: Received file request %1:%2").arg(friendId).arg(fileId); + +} +void CoreFile::onFileControlCallback(Tox* tox, uint32_t friendnumber, uint32_t filenumber, + TOX_FILE_CONTROL control, void *core) +{ + qDebug() << "File control "< +#include +#include + +struct Tox; + +/// Implements Core's file transfer callbacks +/// Avoids polluting core.h with private internal callbacks +class CoreFile +{ +private: + CoreFile()=delete; + +public: + static void onFileReceiveCallback(Tox*, uint32_t friendnumber, uint32_t fileId, uint32_t kind, + uint64_t filesize, const uint8_t *fname, size_t fnameLen, void *core); + static void onFileControlCallback(Tox *tox, uint32_t friendnumber, uint32_t filenumber, + TOX_FILE_CONTROL control, void *core); + static void onFileDataCallback(Tox *tox, uint32_t friendnumber, uint32_t filenumber, + uint64_t pos, size_t length, void *core); + static void onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fileId, uint64_t position, + const uint8_t *data, size_t length, void *core); +}; + +#endif // COREFILE_H diff --git a/src/corestructs.cpp b/src/core/corestructs.cpp similarity index 96% rename from src/corestructs.cpp rename to src/core/corestructs.cpp index d58aacfa6..6dbc73271 100644 --- a/src/corestructs.cpp +++ b/src/core/corestructs.cpp @@ -1,5 +1,5 @@ -#include "src/corestructs.h" -#include "src/core.h" +#include "src/core/corestructs.h" +#include "src/core/core.h" #include #include #include diff --git a/src/corestructs.h b/src/core/corestructs.h similarity index 100% rename from src/corestructs.h rename to src/core/corestructs.h diff --git a/src/friend.cpp b/src/friend.cpp index 767b62010..56cf83960 100644 --- a/src/friend.cpp +++ b/src/friend.cpp @@ -19,7 +19,7 @@ #include "widget/friendwidget.h" #include "widget/form/chatform.h" #include "widget/gui.h" -#include "src/core.h" +#include "src/core/core.h" #include "src/misc/settings.h" Friend::Friend(uint32_t FriendId, const ToxID &UserId) diff --git a/src/friend.h b/src/friend.h index cdf756bf3..8ffb19f5a 100644 --- a/src/friend.h +++ b/src/friend.h @@ -19,7 +19,7 @@ #include #include -#include "corestructs.h" +#include "src/core/corestructs.h" struct FriendWidget; class ChatForm; diff --git a/src/group.cpp b/src/group.cpp index 80b09a3dd..ea975ff90 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -19,7 +19,7 @@ #include "widget/form/groupchatform.h" #include "friendlist.h" #include "friend.h" -#include "core.h" +#include "src/core/core.h" #include "widget/gui.h" #include #include diff --git a/src/historykeeper.cpp b/src/historykeeper.cpp index 4a7a1b467..ac499cb06 100644 --- a/src/historykeeper.cpp +++ b/src/historykeeper.cpp @@ -16,7 +16,7 @@ #include "historykeeper.h" #include "misc/settings.h" -#include "core.h" +#include "src/core/core.h" #include #include diff --git a/src/misc/db/encrypteddb.cpp b/src/misc/db/encrypteddb.cpp index 1a8427aef..885921824 100644 --- a/src/misc/db/encrypteddb.cpp +++ b/src/misc/db/encrypteddb.cpp @@ -16,7 +16,7 @@ #include "encrypteddb.h" #include "src/misc/settings.h" -#include "src/core.h" +#include "src/core/core.h" #include diff --git a/src/misc/serialize.cpp b/src/misc/serialize.cpp index dcf352e85..3d83cc3e6 100644 --- a/src/misc/serialize.cpp +++ b/src/misc/serialize.cpp @@ -154,18 +154,18 @@ QByteArray rangedSingleToData(float value, float min, float max, int numberOfBit numberOfBits -= 8; if (numberOfBits <= 8) { - data += (unsigned char)source>>8; + data += (unsigned char)(source>>8); return data; } - data += (unsigned char)source>>8; + data += (unsigned char)(source>>8); numberOfBits -= 8; if (numberOfBits <= 8) { - data += (unsigned char)source>>16; + data += (unsigned char)(source>>16); return data; } - data += (unsigned char)source>>16; - data += (unsigned char)source>>24; + data += (unsigned char)(source>>16); + data += (unsigned char)(source>>24); return data; } diff --git a/src/misc/settings.cpp b/src/misc/settings.cpp index 88cde4cce..caec9c6e4 100644 --- a/src/misc/settings.cpp +++ b/src/misc/settings.cpp @@ -16,9 +16,9 @@ #include "settings.h" #include "smileypack.h" -#include "src/corestructs.h" +#include "src/core/corestructs.h" #include "src/misc/db/plaindb.h" -#include "src/core.h" +#include "src/core/core.h" #include "src/widget/gui.h" #ifdef QTOX_PLATFORM_EXT #include "src/platform/autorun.h" diff --git a/src/nexus.cpp b/src/nexus.cpp index b7207f8df..260c9b14b 100644 --- a/src/nexus.cpp +++ b/src/nexus.cpp @@ -1,5 +1,5 @@ #include "nexus.h" -#include "core.h" +#include "src/core/core.h" #include "misc/settings.h" #include "video/camera.h" #include "widget/gui.h" diff --git a/src/offlinemsgengine.cpp b/src/offlinemsgengine.cpp index 23acce2c8..1bd8a05ae 100644 --- a/src/offlinemsgengine.cpp +++ b/src/offlinemsgengine.cpp @@ -18,7 +18,7 @@ #include "src/friend.h" #include "src/historykeeper.h" #include "src/misc/settings.h" -#include "src/core.h" +#include "src/core/core.h" #include #include diff --git a/src/toxdns.h b/src/toxdns.h index 91b907d5a..61623634d 100644 --- a/src/toxdns.h +++ b/src/toxdns.h @@ -18,7 +18,7 @@ #ifndef QTOXDNS_H #define QTOXDNS_H -#include "src/corestructs.h" +#include "src/core/corestructs.h" #include #include diff --git a/src/toxme.cpp b/src/toxme.cpp index 6766c46ea..4857ccef7 100644 --- a/src/toxme.cpp +++ b/src/toxme.cpp @@ -1,5 +1,5 @@ #include "toxme.h" -#include "core.h" +#include "src/core/core.h" #include #include #include diff --git a/src/toxme.h b/src/toxme.h index 1382b45c7..07dcc3eb2 100644 --- a/src/toxme.h +++ b/src/toxme.h @@ -4,7 +4,7 @@ #include #include #include -#include "corestructs.h" +#include "src/core/corestructs.h" class QNetworkAccessManager; diff --git a/src/widget/androidgui.cpp b/src/widget/androidgui.cpp index dabaffb43..c64e75524 100644 --- a/src/widget/androidgui.cpp +++ b/src/widget/androidgui.cpp @@ -2,7 +2,7 @@ #include "ui_android.h" #include "friendlistwidget.h" #include "maskablepixmapwidget.h" -#include "src/core.h" +#include "src/core/core.h" #include "src/friend.h" #include "src/friendlist.h" #include "src/group.h" diff --git a/src/widget/androidgui.h b/src/widget/androidgui.h index c27d034fb..158c5e693 100644 --- a/src/widget/androidgui.h +++ b/src/widget/androidgui.h @@ -1,7 +1,7 @@ #ifndef ANDROIDGUI_H #define ANDROIDGUI_H -#include "src/corestructs.h" +#include "src/core/corestructs.h" #include class MaskablePixmapWidget; diff --git a/src/widget/form/addfriendform.cpp b/src/widget/form/addfriendform.cpp index dbd7e4069..4c38082ce 100644 --- a/src/widget/form/addfriendform.cpp +++ b/src/widget/form/addfriendform.cpp @@ -23,7 +23,7 @@ #include #include "ui_mainwindow.h" #include "src/nexus.h" -#include "src/core.h" +#include "src/core/core.h" #include "src/misc/cdata.h" #include "src/toxdns.h" #include "src/misc/settings.h" diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 3097eaac8..c0abf3919 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -24,7 +24,7 @@ #include #include #include "chatform.h" -#include "src/core.h" +#include "src/core/core.h" #include "src/friend.h" #include "src/historykeeper.h" #include "src/misc/style.h" diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h index 0af254646..e6bee18af 100644 --- a/src/widget/form/chatform.h +++ b/src/widget/form/chatform.h @@ -18,7 +18,7 @@ #define CHATFORM_H #include "genericchatform.h" -#include "src/corestructs.h" +#include "src/core/corestructs.h" #include #include #include diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index 760c028e4..09aec7099 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -29,7 +29,7 @@ #include "src/misc/settings.h" #include "src/widget/tool/chattextedit.h" #include "src/widget/maskablepixmapwidget.h" -#include "src/core.h" +#include "src/core/core.h" #include "src/grouplist.h" #include "src/group.h" #include "src/friendlist.h" diff --git a/src/widget/form/genericchatform.h b/src/widget/form/genericchatform.h index d5bb407a3..00eb06cf2 100644 --- a/src/widget/form/genericchatform.h +++ b/src/widget/form/genericchatform.h @@ -21,7 +21,7 @@ #include #include #include -#include "src/corestructs.h" +#include "src/core/corestructs.h" #include "src/chatlog/chatmessage.h" // Spacing in px inserted when the author of the last message changes diff --git a/src/widget/form/groupchatform.cpp b/src/widget/form/groupchatform.cpp index fc4c6d499..a12bc1cbd 100644 --- a/src/widget/form/groupchatform.cpp +++ b/src/widget/form/groupchatform.cpp @@ -21,7 +21,7 @@ #include "src/widget/tool/chattextedit.h" #include "src/widget/croppinglabel.h" #include "src/widget/maskablepixmapwidget.h" -#include "src/core.h" +#include "src/core/core.h" #include "src/misc/style.h" #include #include diff --git a/src/widget/form/profileform.cpp b/src/widget/form/profileform.cpp index 0e05d4d11..280ac83e6 100644 --- a/src/widget/form/profileform.cpp +++ b/src/widget/form/profileform.cpp @@ -14,7 +14,7 @@ See the COPYING file for more details. */ -#include "src/core.h" +#include "src/core/core.h" #include "src/nexus.h" #include "ui_profileform.h" #include "profileform.h" diff --git a/src/widget/form/profileform.h b/src/widget/form/profileform.h index 007d7d9b3..dfb4114a5 100644 --- a/src/widget/form/profileform.h +++ b/src/widget/form/profileform.h @@ -21,7 +21,7 @@ #include #include #include -#include "src/core.h" +#include "src/core/core.h" #include "src/misc/qrwidget.h" class CroppingLabel; diff --git a/src/widget/form/settings/generalform.cpp b/src/widget/form/settings/generalform.cpp index dd10440e8..c1b26fcd8 100644 --- a/src/widget/form/settings/generalform.cpp +++ b/src/widget/form/settings/generalform.cpp @@ -20,7 +20,7 @@ #include "src/widget/widget.h" #include "src/misc/settings.h" #include "src/misc/smileypack.h" -#include "src/core.h" +#include "src/core/core.h" #include "src/misc/style.h" #include #include diff --git a/src/widget/form/settings/privacyform.cpp b/src/widget/form/settings/privacyform.cpp index 85942ad1e..831f84b75 100644 --- a/src/widget/form/settings/privacyform.cpp +++ b/src/widget/form/settings/privacyform.cpp @@ -19,7 +19,7 @@ #include "src/widget/form/settingswidget.h" #include "src/misc/settings.h" #include "src/historykeeper.h" -#include "src/core.h" +#include "src/core/core.h" #include "src/widget/widget.h" #include "src/widget/gui.h" #include "src/widget/form/setpassworddialog.h" diff --git a/src/widget/form/tabcompleter.cpp b/src/widget/form/tabcompleter.cpp index 382fb6c8f..c0f59f482 100644 --- a/src/widget/form/tabcompleter.cpp +++ b/src/widget/form/tabcompleter.cpp @@ -19,7 +19,7 @@ was greatly simplified for use in qTox. */ #include "tabcompleter.h" -#include "src/core.h" +#include "src/core/core.h" #include "src/group.h" #include "src/widget/tool/chattextedit.h" #include diff --git a/src/widget/friendlistwidget.h b/src/widget/friendlistwidget.h index 56aa4deee..ff098ce44 100644 --- a/src/widget/friendlistwidget.h +++ b/src/widget/friendlistwidget.h @@ -19,7 +19,7 @@ #include #include -#include "src/corestructs.h" +#include "src/core/corestructs.h" class QVBoxLayout; class QGridLayout; diff --git a/src/widget/friendwidget.cpp b/src/widget/friendwidget.cpp index 989527825..a2fbf0d80 100644 --- a/src/widget/friendwidget.cpp +++ b/src/widget/friendwidget.cpp @@ -20,7 +20,7 @@ #include "groupwidget.h" #include "src/friendlist.h" #include "src/friend.h" -#include "src/core.h" +#include "src/core/core.h" #include "form/chatform.h" #include "maskablepixmapwidget.h" #include "croppinglabel.h" diff --git a/src/widget/groupwidget.cpp b/src/widget/groupwidget.cpp index 09cb42b68..ffd73b634 100644 --- a/src/widget/groupwidget.cpp +++ b/src/widget/groupwidget.cpp @@ -21,7 +21,7 @@ #include "form/groupchatform.h" #include "maskablepixmapwidget.h" #include "src/misc/style.h" -#include "src/core.h" +#include "src/core/core.h" #include #include #include diff --git a/src/widget/netcamview.cpp b/src/widget/netcamview.cpp index b6bb6c5d8..3de9ed757 100644 --- a/src/widget/netcamview.cpp +++ b/src/widget/netcamview.cpp @@ -15,7 +15,7 @@ */ #include "netcamview.h" -#include "src/core.h" +#include "src/core/core.h" #include "src/widget/videosurface.h" #include #include diff --git a/src/widget/toxsave.cpp b/src/widget/toxsave.cpp index 357424481..f10b98596 100644 --- a/src/widget/toxsave.cpp +++ b/src/widget/toxsave.cpp @@ -16,7 +16,7 @@ #include "toxsave.h" #include "gui.h" -#include "src/core.h" +#include "src/core/core.h" #include "src/misc/settings.h" #include #include diff --git a/src/widget/toxuri.cpp b/src/widget/toxuri.cpp index 26dd1b6c0..dffc1f459 100644 --- a/src/widget/toxuri.cpp +++ b/src/widget/toxuri.cpp @@ -19,7 +19,7 @@ #include "src/toxdns.h" #include "src/widget/tool/friendrequestdialog.h" #include "src/nexus.h" -#include "src/core.h" +#include "src/core/core.h" #include #include #include diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 8e08f1f41..6c8f55ada 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -16,7 +16,7 @@ #include "widget.h" #include "ui_mainwindow.h" -#include "src/core.h" +#include "src/core/core.h" #include "src/misc/settings.h" #include "src/friend.h" #include "src/friendlist.h" diff --git a/src/widget/widget.h b/src/widget/widget.h index 73e299d52..62ad53b4b 100644 --- a/src/widget/widget.h +++ b/src/widget/widget.h @@ -25,7 +25,7 @@ #include "form/settingswidget.h" #include "form/profileform.h" #include "form/filesform.h" -#include "src/corestructs.h" +#include "src/core/corestructs.h" #define PIXELS_TO_ACT 7 From 9dedd22bb26e8581310a03275839a64c45d9809f Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 15:31:30 +0200 Subject: [PATCH 15/51] Port file transfers to the new API Parallel, extremely large, and other edge case transfers have not been tested, but the common path should work well. --- src/chatlog/content/filetransferwidget.cpp | 34 ++- src/chatlog/content/filetransferwidget.h | 4 +- src/core/core.cpp | 207 +-------------- src/core/core.h | 6 +- src/core/corefile.cpp | 286 ++++++++++++++++++++- src/core/corefile.h | 33 ++- src/core/corestructs.cpp | 5 +- src/core/corestructs.h | 5 +- src/ipc.cpp | 1 + 9 files changed, 365 insertions(+), 216 deletions(-) diff --git a/src/chatlog/content/filetransferwidget.cpp b/src/chatlog/content/filetransferwidget.cpp index 466138dbf..2139f445c 100644 --- a/src/chatlog/content/filetransferwidget.cpp +++ b/src/chatlog/content/filetransferwidget.cpp @@ -77,6 +77,7 @@ FileTransferWidget::FileTransferWidget(QWidget *parent, ToxFile file) connect(Core::getInstance(), &Core::fileTransferCancelled, this, &FileTransferWidget::onFileTransferCancelled); connect(Core::getInstance(), &Core::fileTransferPaused, this, &FileTransferWidget::onFileTransferPaused); connect(Core::getInstance(), &Core::fileTransferFinished, this, &FileTransferWidget::onFileTransferFinished); + connect(Core::getInstance(), &Core::fileTransferRemotePausedUnpaused, this, &FileTransferWidget::fileTransferRemotePausedUnpaused); setupButtons(); @@ -222,7 +223,10 @@ void FileTransferWidget::onFileTransferInfo(ToxFile file) // ETA, speed qreal deltaSecs = dt / 1000.0; - qint64 deltaBytes = qMax(file.bytesSent - lastBytesSent, qint64(0)); + // (can't use ::abs or ::max on unsigned types substraction, they'd just overflow) + quint64 deltaBytes = file.bytesSent > lastBytesSent + ? file.bytesSent - lastBytesSent + : lastBytesSent - file.bytesSent; qreal bytesPerSec = static_cast(static_cast(deltaBytes) / deltaSecs); // calculate mean @@ -306,6 +310,26 @@ void FileTransferWidget::onFileTransferPaused(ToxFile file) setupButtons(); } +void FileTransferWidget::onFileTransferResumed(ToxFile file) +{ + if(fileInfo != file) + return; + + fileInfo = file; + + ui->etaLabel->setText(""); + ui->progressLabel->setText(tr("Resuming...", "file transfer widget")); + + // reset mean + meanIndex = 0; + for(size_t i=0; i Core::fileSendQueue; -QList Core::fileRecvQueue; QHash Core::groupCalls; QThread* Core::coreThread{nullptr}; @@ -69,7 +67,6 @@ Core::Core(Camera* cam, QThread *CoreThread, QString loadPath) : toxTimer = new QTimer(this); toxTimer->setSingleShot(true); connect(toxTimer, &QTimer::timeout, this, &Core::process); - //connect(fileTimer, &QTimer::timeout, this, &Core::fileHeartbeat); connect(&Settings::getInstance(), &Settings::dhtServerListChanged, this, &Core::process); for (int i=0; i(core)->checkLastOnline(friendId); + /** TODO: Review file sending breaking/resuming for (ToxFile& f : fileSendQueue) { if (f.friendId == friendId && f.status == ToxFile::TRANSMITTING) @@ -502,9 +500,11 @@ void Core::onConnectionStatusChanged(Tox*/* tox*/, uint32_t friendId, TOX_CONNEC emit static_cast(core)->fileTransferBrokenUnbroken(f, true); } } + */ } else { + /** for (ToxFile& f : fileRecvQueue) { if (f.friendId == friendId && f.status == ToxFile::BROKEN) @@ -514,6 +514,7 @@ void Core::onConnectionStatusChanged(Tox*/* tox*/, uint32_t friendId, TOX_CONNEC emit static_cast(core)->fileTransferBrokenUnbroken(f, false); } } + */ } } @@ -680,186 +681,37 @@ void Core::changeGroupTitle(int groupId, const QString& title) void Core::sendFile(uint32_t friendId, QString Filename, QString FilePath, long long filesize) { - QMutexLocker mlocker(&fileSendMutex); - - QByteArray fileName = Filename.toUtf8(); - uint32_t fileNum = tox_file_send(tox, friendId, TOX_FILE_KIND_DATA, filesize, nullptr, - (uint8_t*)fileName.data(), fileName.size(), nullptr); - if (fileNum == UINT32_MAX) - { - qWarning() << "Core::sendFile: Can't create the Tox file sender"; - emit fileSendFailed(friendId, Filename); - return; - } - qDebug() << QString("Core::sendFile: Created file sender %1 with friend %2").arg(fileNum).arg(friendId); - - ToxFile file{fileNum, friendId, fileName, FilePath, ToxFile::SENDING}; - file.filesize = filesize; - if (!file.open(false)) - { - qWarning() << QString("Core::sendFile: Can't open file, error: %1").arg(file.file->errorString()); - } - fileSendQueue.append(file); - - emit fileSendStarted(fileSendQueue.last()); + CoreFile::sendFile(this, friendId, Filename, FilePath, filesize); } void Core::pauseResumeFileSend(uint32_t friendId, uint32_t fileNum) { - ToxFile* file{nullptr}; - for (ToxFile& f : fileSendQueue) - { - if (f.fileNum == fileNum && f.friendId == friendId) - { - file = &f; - break; - } - } - if (!file) - { - qWarning("Core::pauseResumeFileSend: No such file in queue"); - return; - } - if (file->status == ToxFile::TRANSMITTING) - { - file->status = ToxFile::PAUSED; - emit fileTransferPaused(*file); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_PAUSE, nullptr); - } - else if (file->status == ToxFile::PAUSED) - { - file->status = ToxFile::TRANSMITTING; - emit fileTransferAccepted(*file); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); - } - else - qWarning() << "Core::pauseResumeFileSend: File is stopped"; + CoreFile::pauseResumeFileSend(this, friendId, fileNum); } void Core::pauseResumeFileRecv(uint32_t friendId, uint32_t fileNum) { - ToxFile* file{nullptr}; - for (ToxFile& f : fileRecvQueue) - { - if (f.fileNum == fileNum && f.friendId == friendId) - { - file = &f; - break; - } - } - if (!file) - { - qWarning("Core::cancelFileRecv: No such file in queue"); - return; - } - if (file->status == ToxFile::TRANSMITTING) - { - file->status = ToxFile::PAUSED; - emit fileTransferPaused(*file); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_PAUSE, nullptr); - } - else if (file->status == ToxFile::PAUSED) - { - file->status = ToxFile::TRANSMITTING; - emit fileTransferAccepted(*file); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); - } - else - qWarning() << "Core::pauseResumeFileRecv: File is stopped or broken"; + CoreFile::pauseResumeFileRecv(this, friendId, fileNum); } void Core::cancelFileSend(uint32_t friendId, uint32_t fileNum) { - ToxFile* file{nullptr}; - for (ToxFile& f : fileSendQueue) - { - if (f.fileNum == fileNum && f.friendId == friendId) - { - file = &f; - break; - } - } - if (!file) - { - qWarning("Core::cancelFileSend: No such file in queue"); - return; - } - file->status = ToxFile::STOPPED; - emit fileTransferCancelled(*file); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); - while (file->sendTimer) QThread::msleep(1); // Wait until sendAllFileData returns before deleting - removeFileFromQueue(true, friendId, fileNum); + CoreFile::cancelFileSend(this, friendId, fileNum); } void Core::cancelFileRecv(uint32_t friendId, uint32_t fileNum) { - ToxFile* file{nullptr}; - for (ToxFile& f : fileRecvQueue) - { - if (f.fileNum == fileNum && f.friendId == friendId) - { - file = &f; - break; - } - } - if (!file) - { - qWarning("Core::cancelFileRecv: No such file in queue"); - return; - } - file->status = ToxFile::STOPPED; - emit fileTransferCancelled(*file); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); - removeFileFromQueue(true, friendId, fileNum); + CoreFile::cancelFileRecv(this, friendId, fileNum); } void Core::rejectFileRecvRequest(uint32_t friendId, uint32_t fileNum) { - ToxFile* file{nullptr}; - for (ToxFile& f : fileRecvQueue) - { - if (f.fileNum == fileNum && f.friendId == friendId) - { - file = &f; - break; - } - } - if (!file) - { - qWarning("Core::rejectFileRecvRequest: No such file in queue"); - return; - } - file->status = ToxFile::STOPPED; - emit fileTransferCancelled(*file); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); - removeFileFromQueue(false, friendId, fileNum); + CoreFile::rejectFileRecvRequest(this, friendId, fileNum); } void Core::acceptFileRecvRequest(uint32_t friendId, uint32_t fileNum, QString path) { - ToxFile* file{nullptr}; - for (ToxFile& f : fileRecvQueue) - { - if (f.fileNum == fileNum && f.friendId == friendId) - { - file = &f; - break; - } - } - if (!file) - { - qWarning("Core::acceptFileRecvRequest: No such file in queue"); - return; - } - file->setFilePath(path); - if (!file->open(true)) - { - qWarning() << "Core::acceptFileRecvRequest: Unable to open file"; - return; - } - file->status = ToxFile::TRANSMITTING; - emit fileTransferAccepted(*file); - tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); + CoreFile::acceptFileRecvRequest(this, friendId, fileNum, path); } void Core::removeFriend(uint32_t friendId, bool fake) @@ -1269,43 +1121,6 @@ void Core::quitGroupChat(int groupId) const tox_del_groupchat(tox, groupId); } -void Core::removeFileFromQueue(bool sendQueue, uint32_t friendId, uint32_t fileId) -{ - bool found = false; - if (sendQueue) - { - for (int i=0; iclose(); - delete fileSendQueue[i].file; - fileSendQueue.removeAt(i); - continue; - } - i++; - } - } - else - { - for (int i=0; iclose(); - delete fileRecvQueue[i].file; - fileRecvQueue.removeAt(i); - continue; - } - i++; - } - } - if (!found) - qWarning() << "Core::removeFileFromQueue: No such file in queue"; -} - void Core::groupInviteFriend(uint32_t friendId, int groupId) { tox_invite_friend(tox, friendId, groupId); diff --git a/src/core/core.h b/src/core/core.h index e01b7d5ae..32105b29e 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -278,8 +278,6 @@ private: void make_tox(QByteArray savedata); void loadFriends(); - static void removeFileFromQueue(bool sendQueue, uint32_t friendId, uint32_t fileId); - void checkLastOnline(uint32_t friendId); void deadifyTox(); @@ -292,13 +290,12 @@ private: QString loadPath; // meaningless after start() is called QList dhtServerList; int dhtServerId; - static QList fileSendQueue, fileRecvQueue; static ToxCall calls[TOXAV_MAX_CALLS]; #ifdef QTOX_FILTER_AUDIO static AudioFilterer * filterer[TOXAV_MAX_CALLS]; #endif static QHash groupCalls; // Maps group IDs to ToxGroupCalls - QMutex fileSendMutex, messageSendMutex; + QMutex messageSendMutex; bool ready; TOX_PASS_KEY* pwsaltedkeys[PasswordType::ptCounter] = {nullptr}; // use the pw's hash as the "pw" @@ -319,6 +316,7 @@ private: static QThread *coreThread; friend class Audio; ///< Audio can access our calls directly to reduce latency + friend class CoreFile; ///< CoreFile can access tox* and emit our signals }; #endif // CORE_HPP diff --git a/src/core/corefile.cpp b/src/core/corefile.cpp index d636d25c7..893106bd1 100644 --- a/src/core/corefile.cpp +++ b/src/core/corefile.cpp @@ -1,26 +1,298 @@ +#include "core.h" #include "corefile.h" +#include "corestructs.h" +#include "src/misc/cstring.h" #include +#include +#include +#include + +QMutex CoreFile::fileSendMutex; +QHash CoreFile::fileMap; +using namespace std; + +void CoreFile::sendFile(Core* core, uint32_t friendId, QString Filename, QString FilePath, long long filesize) +{ + QMutexLocker mlocker(&fileSendMutex); + + QByteArray fileName = Filename.toUtf8(); + uint32_t fileNum = tox_file_send(core->tox, friendId, TOX_FILE_KIND_DATA, filesize, nullptr, + (uint8_t*)fileName.data(), fileName.size(), nullptr); + if (fileNum == UINT32_MAX) + { + qWarning() << "CoreFile::sendFile: Can't create the Tox file sender"; + emit core->fileSendFailed(friendId, Filename); + return; + } + qDebug() << QString("CoreFile::sendFile: Created file sender %1 with friend %2").arg(fileNum).arg(friendId); + + ToxFile file{fileNum, friendId, fileName, FilePath, ToxFile::SENDING}; + file.filesize = filesize; + if (!file.open(false)) + { + qWarning() << QString("CoreFile::sendFile: Can't open file, error: %1").arg(file.file->errorString()); + } + addFile(friendId, fileNum, file); + + emit core->fileSendStarted(file); +} + +void CoreFile::pauseResumeFileSend(Core* core, uint32_t friendId, uint32_t fileId) +{ + ToxFile* file = findFile(friendId, fileId); + if (!file) + { + qWarning("CoreFile::pauseResumeFileSend: No such file in queue"); + return; + } + if (file->status == ToxFile::TRANSMITTING) + { + file->status = ToxFile::PAUSED; + emit core->fileTransferPaused(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_PAUSE, nullptr); + } + else if (file->status == ToxFile::PAUSED) + { + file->status = ToxFile::TRANSMITTING; + emit core->fileTransferAccepted(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); + } + else + qWarning() << "CoreFile::pauseResumeFileSend: File is stopped"; +} + +void CoreFile::pauseResumeFileRecv(Core* core, uint32_t friendId, uint32_t fileId) +{ + ToxFile* file = findFile(friendId, fileId); + if (!file) + { + qWarning("CoreFile::cancelFileRecv: No such file in queue"); + return; + } + if (file->status == ToxFile::TRANSMITTING) + { + file->status = ToxFile::PAUSED; + emit core->fileTransferPaused(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_PAUSE, nullptr); + } + else if (file->status == ToxFile::PAUSED) + { + file->status = ToxFile::TRANSMITTING; + emit core->fileTransferAccepted(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); + } + else + qWarning() << "CoreFile::pauseResumeFileRecv: File is stopped or broken"; +} + +void CoreFile::cancelFileSend(Core* core, uint32_t friendId, uint32_t fileId) +{ + ToxFile* file = findFile(friendId, fileId); + if (!file) + { + qWarning("CoreFile::cancelFileSend: No such file in queue"); + return; + } + file->status = ToxFile::STOPPED; + emit core->fileTransferCancelled(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); + while (file->sendTimer) QThread::msleep(1); // Wait until sendAllFileData returns before deleting + removeFile(friendId, fileId); +} + +void CoreFile::cancelFileRecv(Core* core, uint32_t friendId, uint32_t fileId) +{ + ToxFile* file = findFile(friendId, fileId); + if (!file) + { + qWarning("CoreFile::cancelFileRecv: No such file in queue"); + return; + } + file->status = ToxFile::STOPPED; + emit core->fileTransferCancelled(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); + removeFile(friendId, fileId); +} + +void CoreFile::rejectFileRecvRequest(Core* core, uint32_t friendId, uint32_t fileId) +{ + ToxFile* file = findFile(friendId, fileId); + if (!file) + { + qWarning("CoreFile::rejectFileRecvRequest: No such file in queue"); + return; + } + file->status = ToxFile::STOPPED; + emit core->fileTransferCancelled(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); + removeFile(friendId, fileId); +} + +void CoreFile::acceptFileRecvRequest(Core* core, uint32_t friendId, uint32_t fileId, QString path) +{ + ToxFile* file = findFile(friendId, fileId); + if (!file) + { + qWarning("CoreFile::acceptFileRecvRequest: No such file in queue"); + return; + } + file->setFilePath(path); + if (!file->open(true)) + { + qWarning() << "CoreFile::acceptFileRecvRequest: Unable to open file"; + return; + } + file->status = ToxFile::TRANSMITTING; + emit core->fileTransferAccepted(*file); + tox_file_control(core->tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr); +} + +ToxFile* CoreFile::findFile(uint32_t friendId, uint32_t fileId) +{ + uint64_t key = ((uint64_t)friendId<<32) + (uint64_t)fileId; + if (!fileMap.contains(key)) + { + qWarning() << "CoreFile::addFile: File transfer with ID "<(core)->fileReceiveRequested(file); } -void CoreFile::onFileControlCallback(Tox* tox, uint32_t friendnumber, uint32_t filenumber, +void CoreFile::onFileControlCallback(Tox*, uint32_t friendId, uint32_t fileId, TOX_FILE_CONTROL control, void *core) { - qDebug() << "File control "<(core)->fileTransferCancelled(*file); + removeFile(friendId, fileId); + } + else if (control == TOX_FILE_CONTROL_PAUSE) + { + qDebug() << "CoreFile::onFileControlCallback: Received pause for file "<status = ToxFile::PAUSED; + emit static_cast(core)->fileTransferRemotePausedUnpaused(*file, true); + } + else if (control == TOX_FILE_CONTROL_RESUME) + { + qDebug() << "CoreFile::onFileControlCallback: Received pause for file "<status = ToxFile::TRANSMITTING; + emit static_cast(core)->fileTransferRemotePausedUnpaused(*file, false); + } + else + { + qWarning() << "Unhandled file control "<(core)->fileTransferFinished(*file); + removeFile(friendId, fileId); + return; + } + + unique_ptr data(new uint8_t[length]); + + file->file->seek(pos); + int64_t nread = file->file->read((char*)data.get(), length); + if (nread <= 0) + { + qWarning("CoreFile::onFileDataCallback: Failed to read from file"); + emit static_cast(core)->fileTransferCancelled(*file); + tox_file_send_chunk(tox, friendId, fileId, pos, nullptr, 0, nullptr); + removeFile(friendId, fileId); + return; + } + file->bytesSent += length; + + if (!tox_file_send_chunk(tox, friendId, fileId, pos, data.get(), nread, nullptr)) + { + qWarning("CoreFile::onFileDataCallback: Failed to send data chunk"); + return; + } + emit static_cast(core)->fileTransferInfo(*file); } void CoreFile::onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fileId, uint64_t position, const uint8_t *data, size_t length, void *core) { - qDebug() << QString("Core: Received file chunk for request %1:%2").arg(friendId).arg(fileId); + //qDebug() << QString("CoreFile: Received file chunk for request %1:%2").arg(friendId).arg(fileId); + + ToxFile* file = findFile(friendId, fileId); + if (!file) + { + qWarning("CoreFile::onFileRecvChunkCallback: No such file in queue"); + tox_file_control(tox, friendId, fileId, TOX_FILE_CONTROL_CANCEL, nullptr); + return; + } + + if (file->bytesSent != position) + { + /// TODO: Allow ooo receiving for non-stream transfers, with very careful checking + qWarning("CoreFile::onFileRecvChunkCallback: Received a chunk out-of-order, aborting transfer"); + emit static_cast(core)->fileTransferCancelled(*file); + tox_file_control(tox, friendId, fileId, TOX_FILE_CONTROL_CANCEL, nullptr); + removeFile(friendId, fileId); + return; + } + file->bytesSent += length; + file->file->write((char*)data,length); + //qDebug() << QString("CoreFile::onFileRecvChunkCallback: received %1/%2 bytes").arg(file->bytesSent).arg(file->filesize); + + if (file->bytesSent == file->filesize) + emit static_cast(core)->fileTransferFinished(*file); + else + emit static_cast(core)->fileTransferInfo(*file); } diff --git a/src/core/corefile.h b/src/core/corefile.h index 1be64422d..cf8816524 100644 --- a/src/core/corefile.h +++ b/src/core/corefile.h @@ -3,26 +3,53 @@ #include #include +#include #include +#include "corestructs.h" + +#include +#include +#include + struct Tox; +class Core; /// Implements Core's file transfer callbacks /// Avoids polluting core.h with private internal callbacks class CoreFile { + friend class Core; + private: CoreFile()=delete; -public: +private: + static void sendFile(Core *core, uint32_t friendId, QString Filename, QString FilePath, long long filesize); + static void pauseResumeFileSend(Core* core, uint32_t friendId, uint32_t fileId); + static void pauseResumeFileRecv(Core* core, uint32_t friendId, uint32_t fileId); + static void cancelFileSend(Core* core, uint32_t friendId, uint32_t fileId); + static void cancelFileRecv(Core* core, uint32_t friendId, uint32_t fileId); + static void rejectFileRecvRequest(Core* core, uint32_t friendId, uint32_t fileId); + static void acceptFileRecvRequest(Core* core, uint32_t friendId, uint32_t fileId, QString path); + static ToxFile *findFile(uint32_t friendId, uint32_t fileId); + static void addFile(uint32_t friendId, uint32_t fileId, const ToxFile& file); + static void removeFile(uint32_t friendId, uint32_t fileId); + +private: static void onFileReceiveCallback(Tox*, uint32_t friendnumber, uint32_t fileId, uint32_t kind, uint64_t filesize, const uint8_t *fname, size_t fnameLen, void *core); - static void onFileControlCallback(Tox *tox, uint32_t friendnumber, uint32_t filenumber, + static void onFileControlCallback(Tox *tox, uint32_t friendId, uint32_t fileId, TOX_FILE_CONTROL control, void *core); - static void onFileDataCallback(Tox *tox, uint32_t friendnumber, uint32_t filenumber, + static void onFileDataCallback(Tox *tox, uint32_t friendId, uint32_t fileId, uint64_t pos, size_t length, void *core); static void onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fileId, uint64_t position, const uint8_t *data, size_t length, void *core); + +private: + static QMutex fileSendMutex; + static QHash fileMap; + /// TODO: Replace the two queues by a hash map uint64_t -> unique_ptr }; #endif // COREFILE_H diff --git a/src/core/corestructs.cpp b/src/core/corestructs.cpp index 6dbc73271..20362b9bb 100644 --- a/src/core/corestructs.cpp +++ b/src/core/corestructs.cpp @@ -7,8 +7,9 @@ #define TOX_HEX_ID_LENGTH 2*TOX_ADDRESS_SIZE ToxFile::ToxFile(uint32_t FileNum, uint32_t FriendId, QByteArray FileName, QString FilePath, FileDirection Direction) - : fileNum(FileNum), friendId(FriendId), fileName{FileName}, filePath{FilePath}, file{new QFile(filePath)}, - bytesSent{0}, filesize{0}, status{STOPPED}, direction{Direction}, sendTimer{nullptr} + : fileKind{TOX_FILE_KIND_DATA}, fileNum(FileNum), friendId(FriendId), fileName{FileName}, + filePath{FilePath}, file{new QFile(filePath)}, bytesSent{0}, filesize{0}, + status{STOPPED}, direction{Direction}, sendTimer{nullptr} { } diff --git a/src/core/corestructs.h b/src/core/corestructs.h index d6bc81ae3..fc16c852e 100644 --- a/src/core/corestructs.h +++ b/src/core/corestructs.h @@ -67,13 +67,14 @@ struct ToxFile void setFilePath(QString path); bool open(bool write); + uint8_t fileKind; ///< Data file (default) or avatar uint32_t fileNum; uint32_t friendId; QByteArray fileName; QString filePath; QFile* file; - qint64 bytesSent; - qint64 filesize; + quint64 bytesSent; + quint64 filesize; FileStatus status; FileDirection direction; QTimer* sendTimer; diff --git a/src/ipc.cpp b/src/ipc.cpp index 8609c9a12..222de3e0a 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -134,6 +134,7 @@ bool IPC::isCurrentOwner() { if (globalMemory.lock()) { + /// TODO: Segfault on exit on "mov rdx,QWORD PTR [rax]" w/ rax=0. bool isOwner = ((*(uint64_t*)globalMemory.data()) == globalId); globalMemory.unlock(); return isOwner; From 66314bc38dcb6fa9b68d3363c6cf015b1c97b9d2 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 15:38:21 +0200 Subject: [PATCH 16/51] Fix nullptr dereference in IPC::isCurrentOwner It would only trigger when multiple instances where running in parallel, with one having enough privilege to block the other from accessing the shared memory (e.g. root) --- src/ipc.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ipc.cpp b/src/ipc.cpp index 222de3e0a..858dc4195 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -134,8 +134,14 @@ bool IPC::isCurrentOwner() { if (globalMemory.lock()) { - /// TODO: Segfault on exit on "mov rdx,QWORD PTR [rax]" w/ rax=0. - bool isOwner = ((*(uint64_t*)globalMemory.data()) == globalId); + void* data = globalMemory.data(); + if (!data) + { + qWarning() << "IPC: isCurrentOwner failed to access the memory, returning false"; + globalMemory.unlock(); + return false; + } + bool isOwner = ((*(uint64_t*)data) == globalId); globalMemory.unlock(); return isOwner; } From 92f3b6a20fb1b3a72d4c103a36e9b72c51143407 Mon Sep 17 00:00:00 2001 From: Zetok Zalbavar Date: Fri, 24 Apr 2015 12:01:50 +0100 Subject: [PATCH 17/51] Code style improvements --- src/audio.cpp | 11 +++-- src/chatlog/content/filetransferwidget.cpp | 3 ++ src/core/core.cpp | 10 +++-- src/core/coreav.cpp | 8 ++-- src/core/coreencryption.cpp | 8 ++++ src/friend.cpp | 1 + src/group.cpp | 3 +- src/historykeeper.cpp | 15 ++++--- src/misc/db/encrypteddb.cpp | 18 ++++---- src/misc/settings.cpp | 47 ++++++++++++++------- src/nexus.cpp | 3 ++ src/offlinemsgengine.cpp | 1 + src/toxme.cpp | 6 +++ src/widget/form/addfriendform.cpp | 15 +++++-- src/widget/form/chatform.cpp | 18 ++++---- src/widget/form/genericchatform.cpp | 4 +- src/widget/form/groupchatform.cpp | 5 +++ src/widget/form/profileform.cpp | 3 ++ src/widget/form/settings/generalform.cpp | 13 +++--- src/widget/form/settings/privacyform.cpp | 2 + src/widget/form/tabcompleter.cpp | 17 +++++--- src/widget/groupwidget.cpp | 4 +- src/widget/toxsave.cpp | 2 - src/widget/toxuri.cpp | 2 - src/widget/widget.cpp | 49 ++++++++++++---------- 25 files changed, 173 insertions(+), 95 deletions(-) diff --git a/src/audio.cpp b/src/audio.cpp index 47b338218..e2cfb6d1a 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -72,6 +72,7 @@ Audio::~Audio() audioThread->wait(); if (audioThread->isRunning()) audioThread->terminate(); + delete audioThread; delete audioInLock; delete audioOutLock; @@ -123,6 +124,7 @@ void Audio::openInput(const QString& inDevDescr) alInDev = nullptr; if (tmp) alcCaptureCloseDevice(tmp); + int stereoFlag = av_DefaultSettings.audio_channels==1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; if (inDevDescr.isEmpty()) alInDev = alcCaptureOpenDevice(nullptr,av_DefaultSettings.audio_sample_rate, stereoFlag, @@ -163,6 +165,7 @@ void Audio::openOutput(const QString& outDevDescr) alOutDev = alcOpenDevice(nullptr); else alOutDev = alcOpenDevice(outDevDescr.toStdString().c_str()); + if (!alOutDev) { qWarning() << "Audio: Cannot open output audio device"; @@ -171,8 +174,10 @@ void Audio::openOutput(const QString& outDevDescr) { if (alContext && alcMakeContextCurrent(nullptr) == ALC_TRUE) alcDestroyContext(alContext); + if (tmp) alcCloseDevice(tmp); + alContext=alcCreateContext(alOutDev,nullptr); if (!alcMakeContextCurrent(alContext)) { @@ -180,7 +185,9 @@ void Audio::openOutput(const QString& outDevDescr) alcCloseDevice(alOutDev); } else + { alGenSources(1, &alMainSource); + } qDebug() << "Audio: Opening audio output "<progressLabel->setText(tr("Waiting to send...", "file transfer widget")); } else + { ui->progressLabel->setText(tr("Accept to receive this file", "file transfer widget")); + } setFixedHeight(78); } @@ -187,6 +189,7 @@ void FileTransferWidget::paintEvent(QPaintEvent *) // draw background if(drawButtonAreaNeeded()) painter.setClipRect(QRect(0,0,width()-buttonFieldWidth,height())); + painter.setBrush(QBrush(backgroundColor)); painter.drawRoundRect(geometry(), r * ratio, r); diff --git a/src/core/core.cpp b/src/core/core.cpp index 2c93b7069..4e915dcdf 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -457,7 +457,8 @@ void Core::onStatusMessageChanged(Tox*/* tox*/, uint32_t friendId, const uint8_t void Core::onUserStatusChanged(Tox*/* tox*/, uint32_t friendId, TOX_USER_STATUS userstatus, void* core) { Status status; - switch (userstatus) { + switch (userstatus) + { case TOX_USER_STATUS_NONE: status = Status::Online; break; @@ -611,6 +612,7 @@ void Core::requestFriendship(const QString& friendAddress, const QString& messag QString inviteStr = tr("/me offers friendship."); if (message.length()) inviteStr = tr("/me offers friendship, \"%1\"").arg(message); + HistoryKeeper::getInstance()->addChatEntry(userId, inviteStr, getSelfId().publicKey, QDateTime::currentDateTime(), true); emit friendAdded(friendId, userId); } @@ -826,7 +828,8 @@ void Core::setStatusMessage(const QString& message) { CString cMessage(message); - if (tox_self_set_status_message(tox, cMessage.data(), cMessage.size(), nullptr) == false) { + if (tox_self_set_status_message(tox, cMessage.data(), cMessage.size(), nullptr) == false) + { emit failedToSetStatusMessage(message); } else @@ -900,7 +903,8 @@ QByteArray Core::loadToxSave(QString path) if (fileSize > 0) { data = configurationFile.readAll(); - if (tox_is_data_encrypted((uint8_t*)data.data())) { + if (tox_is_data_encrypted((uint8_t*)data.data())) + { if (!loadEncryptedSave(data)) { configurationFile.close(); diff --git a/src/core/coreav.cpp b/src/core/coreav.cpp index 9e44457b9..7900e713d 100644 --- a/src/core/coreav.cpp +++ b/src/core/coreav.cpp @@ -34,8 +34,10 @@ uint8_t* Core::videobuf; bool Core::anyActiveCalls() { for (auto& call : calls) + { if (call.active) return true; + } return false; } @@ -93,6 +95,7 @@ void Core::onAvMediaChange(void* toxav, int32_t callId, void* core) int friendId; if (toxav_get_peer_csettings((ToxAv*)toxav, callId, 0, &settings) < 0) goto fail; + friendId = toxav_get_peer_id((ToxAv*)toxav, callId, 0); if (friendId < 0) goto fail; @@ -220,6 +223,7 @@ void Core::cleanupCall(int32_t callId) calls[callId].sendVideoTimer->stop(); if (calls[callId].videoEnabled) Camera::getInstance()->unsubscribe(); + Audio::unsuscribeInput(); toxav_kill_transmission(Core::getInstance()->toxav, callId); } @@ -286,9 +290,7 @@ void Core::sendCallAudio(int32_t callId, ToxAv* toxav) } if ((r = toxav_send_audio(toxav, callId, dest, r)) < 0) - { qDebug() << "Core: toxav_send_audio error"; - } } calls[callId].sendAudioTimer->start(); } @@ -336,9 +338,7 @@ void Core::sendCallVideo(int32_t callId) void Core::micMuteToggle(int32_t callId) { if (calls[callId].active) - { calls[callId].muteMic = !calls[callId].muteMic; - } } void Core::volMuteToggle(int32_t callId) diff --git a/src/core/coreencryption.cpp b/src/core/coreencryption.cpp index 2df15fe57..864aca6de 100644 --- a/src/core/coreencryption.cpp +++ b/src/core/coreencryption.cpp @@ -190,7 +190,9 @@ bool Core::loadEncryptedSave(QByteArray& data) dialogtxt = tr("The profile password failed. Please try another?", "used only when pw set before load() doesn't work"); } else + { dialogtxt = a; + } uint8_t salt[TOX_PASS_SALT_LENGTH]; tox_get_salt(reinterpret_cast(data.data()), salt); @@ -205,7 +207,9 @@ bool Core::loadEncryptedSave(QByteArray& data) return false; } else + { setPassword(pw, ptMain, salt); + } QByteArray newData(fileSize-TOX_PASS_ENCRYPTION_EXTRA_LENGTH, 0); error = !tox_pass_key_decrypt((uint8_t*)data.data(), data.size(), pwsaltedkeys[ptMain], @@ -248,7 +252,9 @@ void Core::checkEncryptedHistory() dialogtxt = tr("The chat history password failed. Please try another?", "used only when pw set before load() doesn't work"); } else + { dialogtxt = a; + } dialogtxt += "\n" + c; @@ -341,7 +347,9 @@ void Core::saveConfiguration(const QString& path) } } else + { tox_get_savedata(tox, data); + } configurationFile.write(reinterpret_cast(data), fileSize); configurationFile.commit(); diff --git a/src/friend.cpp b/src/friend.cpp index 56cf83960..82f66cb30 100644 --- a/src/friend.cpp +++ b/src/friend.cpp @@ -87,6 +87,7 @@ QString Friend::getDisplayedName() const { if (userAlias.size() == 0) return userName; + return userAlias; } diff --git a/src/group.cpp b/src/group.cpp index ea975ff90..78932545c 100644 --- a/src/group.cpp +++ b/src/group.cpp @@ -102,6 +102,7 @@ void Group::regeneratePeerList() ToxID id = Core::getInstance()->getGroupPeerToxID(groupId, i); if (id.isMine()) selfPeerNum = i; + QString toxid = id.publicKey; toxids[toxid] = peers[i]; Friend *f = FriendList::findFriend(id); @@ -177,9 +178,7 @@ QString Group::resolveToxID(const ToxID &id) const auto it = toxids.find(key); if (it != toxids.end()) - { return *it; - } return QString(); } diff --git a/src/historykeeper.cpp b/src/historykeeper.cpp index ac499cb06..2a78cfa6e 100644 --- a/src/historykeeper.cpp +++ b/src/historykeeper.cpp @@ -56,7 +56,9 @@ HistoryKeeper *HistoryKeeper::getInstance() historyInstance = new HistoryKeeper(dbIntf); return historyInstance; - } else { + } + else + { path = getHistoryPath(); } } @@ -111,9 +113,7 @@ HistoryKeeper::HistoryKeeper(GenericDdInterface *db_) : QSqlQuery ret = db->exec("SELECT seq FROM sqlite_sequence WHERE name=\"sent_status\";"); int idCur = 0; if (ret.first()) - { idCur = ret.value(0).toInt(); - } if (idCur != idMax) { @@ -145,6 +145,7 @@ qint64 HistoryKeeper::addChatEntry(const QString& chat, const QString& message, db->exec("BEGIN TRANSACTION;"); for (auto &it : cmds) db->exec(it); + db->exec("COMMIT TRANSACTION;"); messageID++; @@ -167,7 +168,9 @@ QList HistoryKeeper::getChatHistory(HistoryKeeper::C dbAnswer = db->exec(QString("SELECT history.id, timestamp, user_id, message, status 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 { + } + else + { // no groupchats yet } @@ -372,7 +375,8 @@ void HistoryKeeper::setSyncType(Db::syncType sType) { QString syncCmd; - switch (sType) { + switch (sType) + { case Db::syncType::stFull: syncCmd = "FULL"; break; @@ -413,5 +417,6 @@ QList HistoryKeeper::exportMessagesDeleteFile(int en qDebug() << "HistoryKeeper: count" << msgs.size() << "messages exported"; if (!removeHistory(encrypted)) qWarning() << "HistoryKeeper: couldn't delete old log file!"; + return msgs; } diff --git a/src/misc/db/encrypteddb.cpp b/src/misc/db/encrypteddb.cpp index 885921824..1228dc21d 100644 --- a/src/misc/db/encrypteddb.cpp +++ b/src/misc/db/encrypteddb.cpp @@ -41,7 +41,9 @@ EncryptedDb::EncryptedDb(const QString &fname, QList initList) : encrFile.close(); } else + { chunkPosition = 0; + } encrFile.setFileName(fileName); @@ -90,7 +92,9 @@ bool EncryptedDb::pullFileContent(const QString &fname, QByteArray &buf) if (buf.size() > 0) { fileContent += buf; - } else { + } + else + { qWarning() << "EncryptedDb::pullFileContent: Encrypted history log is corrupted: can't decrypt, will be deleted"; buf = QByteArray(); return false; @@ -108,9 +112,8 @@ bool EncryptedDb::pullFileContent(const QString &fname, QByteArray &buf) PlainDb::exec("BEGIN TRANSACTION;"); for (auto line : sqlCmds) - { QSqlQuery r = PlainDb::exec(line); - } + PlainDb::exec("COMMIT TRANSACTION;"); dbFile.close(); @@ -144,9 +147,8 @@ void EncryptedDb::appendToEncrypted(const QString &sql) QByteArray encr = Core::getInstance()->encryptData(buffer, Core::ptHistory); if (encr.size() > 0) - { encrFile.write(encr); - } + encrFile.flush(); } @@ -161,10 +163,10 @@ bool EncryptedDb::check(const QString &fname) QByteArray encrChunk = file.read(encryptedChunkSize); QByteArray buf = Core::getInstance()->decryptData(encrChunk, Core::ptHistory); if (buf.size() == 0) - { state = false; - } - } else { + } + else + { file.close(); file.open(QIODevice::WriteOnly); } diff --git a/src/misc/settings.cpp b/src/misc/settings.cpp index caec9c6e4..c02a406c0 100644 --- a/src/misc/settings.cpp +++ b/src/misc/settings.cpp @@ -54,6 +54,7 @@ Settings& Settings::getInstance() { if (!settings) settings = new Settings(); + return *settings; } @@ -92,7 +93,9 @@ QString Settings::detectProfile() { profile = askProfiles(); if (profile.isEmpty()) + { return ""; + } else { switchProfile(profile); @@ -101,7 +104,9 @@ QString Settings::detectProfile() } } else + { return path; + } } QList Settings::searchProfiles() @@ -112,6 +117,7 @@ QList Settings::searchProfiles() dir.setNameFilters(QStringList("*.tox")); for (QFileInfo file : dir.entryInfoList()) out += file.completeBaseName(); + return out; } @@ -154,7 +160,9 @@ void Settings::load() ps.endGroup(); } else + { makeToxPortable = false; + } QDir dir(getSettingsDirPath()); QString filePath = dir.filePath(FILENAME); @@ -178,7 +186,8 @@ void Settings::load() useCustomDhtList = true; qDebug() << "Using custom bootstrap nodes list"; int serverListSize = s.beginReadArray("dhtServerList"); - for (int i = 0; i < serverListSize; i ++) { + for (int i = 0; i < serverListSize; i ++) + { s.setArrayIndex(i); DhtServer server; server.name = s.value("name").toString(); @@ -190,7 +199,9 @@ void Settings::load() s.endArray(); } else + { useCustomDhtList=false; + } s.endGroup(); s.beginGroup("General"); @@ -228,9 +239,9 @@ void Settings::load() s.beginGroup("Widgets"); QList objectNames = s.childKeys(); - for (const QString& name : objectNames) { + for (const QString& name : objectNames) widgetSettings[name] = s.value(name).toByteArray(); - } + s.endGroup(); s.beginGroup("GUI"); @@ -283,7 +294,8 @@ void Settings::load() QSettings rcs(":/conf/settings.ini", QSettings::IniFormat); rcs.beginGroup("DHT Server"); int serverListSize = rcs.beginReadArray("dhtServerList"); - for (int i = 0; i < serverListSize; i ++) { + for (int i = 0; i < serverListSize; i ++) + { rcs.setArrayIndex(i); DhtServer server; server.name = rcs.value("name").toString(); @@ -357,7 +369,8 @@ void Settings::saveGlobal(QString path) s.beginGroup("DHT Server"); s.setValue("useCustomList", useCustomDhtList); s.beginWriteArray("dhtServerList", dhtServerList.size()); - for (int i = 0; i < dhtServerList.size(); i ++) { + for (int i = 0; i < dhtServerList.size(); i ++) + { s.setArrayIndex(i); s.setValue("name", dhtServerList[i].name); s.setValue("userId", dhtServerList[i].userId); @@ -398,9 +411,9 @@ void Settings::saveGlobal(QString path) s.beginGroup("Widgets"); const QList widgetNames = widgetSettings.keys(); - for (const QString& name : widgetNames) { + for (const QString& name : widgetNames) s.setValue(name, widgetSettings.value(name)); - } + s.endGroup(); s.beginGroup("GUI"); @@ -505,12 +518,15 @@ QPixmap Settings::getSavedAvatar(const QString &ownerId) QString filePath = dir.filePath("avatar_"+ownerId.left(64)); if (!QFileInfo(filePath).exists()) // try without truncation, for old self avatars filePath = dir.filePath("avatar_"+ownerId); + pic.load(filePath); saveAvatar(pic, ownerId); QFile::remove(filePath); } else + { pic.load(filePath); + } return pic; } @@ -530,6 +546,7 @@ void Settings::saveAvatarHash(const QByteArray& hash, const QString& ownerId) QFile file(dir.filePath("avatars/"+ownerId.left(64)+".hash")); if (!file.open(QIODevice::WriteOnly)) return; + file.write(hash); file.close(); } @@ -541,6 +558,7 @@ QByteArray Settings::getAvatarHash(const QString& ownerId) QFile file(dir.filePath("avatars/"+ownerId.left(64)+".hash")); if (!file.open(QIODevice::ReadOnly)) return QByteArray(); + QByteArray out = file.readAll(); file.close(); return out; @@ -840,6 +858,7 @@ void Settings::setAutoAwayTime(int newValue) { if (newValue < 0) newValue = 10; + autoAwayTime = newValue; } @@ -849,9 +868,7 @@ QString Settings::getAutoAcceptDir(const ToxID& id) const auto it = friendLst.find(key); if (it != friendLst.end()) - { return it->autoAcceptDir; - } return QString(); } @@ -1110,9 +1127,7 @@ QString Settings::getFriendAdress(const QString &publicKey) const QString key = ToxID::fromString(publicKey).publicKey; auto it = friendLst.find(key); if (it != friendLst.end()) - { return it->addr; - } return QString(); } @@ -1124,7 +1139,9 @@ void Settings::updateFriendAdress(const QString &newAddr) if (it != friendLst.end()) { it->addr = newAddr; - } else { + } + else + { friendProp fp; fp.addr = newAddr; fp.alias = ""; @@ -1138,9 +1155,7 @@ QString Settings::getFriendAlias(const ToxID &id) const QString key = id.publicKey; auto it = friendLst.find(key); if (it != friendLst.end()) - { return it->alias; - } return QString(); } @@ -1152,7 +1167,9 @@ void Settings::setFriendAlias(const ToxID &id, const QString &alias) if (it != friendLst.end()) { it->alias = alias; - } else { + } + else + { friendProp fp; fp.addr = key; fp.alias = alias; diff --git a/src/nexus.cpp b/src/nexus.cpp index 260c9b14b..2473dcbb5 100644 --- a/src/nexus.cpp +++ b/src/nexus.cpp @@ -40,6 +40,7 @@ void Nexus::start() { if (started) return; + qDebug() << "Nexus: Starting up"; // Setup the environment @@ -139,6 +140,7 @@ Nexus& Nexus::getInstance() { if (!nexus) nexus = new Nexus; + return *nexus; } @@ -168,6 +170,7 @@ QString Nexus::getSupportedImageFilter() QString res; for (auto type : QImageReader::supportedImageFormats()) res += QString("*.%1 ").arg(QString(type)); + return tr("Images (%1)", "filetype filter").arg(res.left(res.size()-1)); } diff --git a/src/offlinemsgengine.cpp b/src/offlinemsgengine.cpp index 1bd8a05ae..fce43c1bc 100644 --- a/src/offlinemsgengine.cpp +++ b/src/offlinemsgengine.cpp @@ -91,6 +91,7 @@ void OfflineMsgEngine::deliverOfflineMsgs() rec = Core::getInstance()->sendAction(f->getFriendID(), messageText); else rec = Core::getInstance()->sendMessage(f->getFriendID(), messageText); + registerReceipt(rec, iter.key(), iter.value().msg); } } diff --git a/src/toxme.cpp b/src/toxme.cpp index 4857ccef7..af95a2925 100644 --- a/src/toxme.cpp +++ b/src/toxme.cpp @@ -69,16 +69,19 @@ ToxID Toxme::lookup(QString address) const int index = response.indexOf(pattern); if (index == -1) return id; + response = response.mid(index+pattern.size()); const int idStart = response.indexOf('"'); if (idStart == -1) return id; + response = response.mid(idStart+1); const int idEnd = response.indexOf('"'); if (idEnd == -1) return id; + response.truncate(idEnd); id = ToxID::fromString(response); @@ -93,17 +96,20 @@ int Toxme::extractError(QString json) const int index = json.indexOf(pattern); if (index == -1) return INT_MIN; + json = json.mid(index+pattern.size()); const int end = json.indexOf('}'); if (end == -1) return INT_MIN; + json.truncate(end); bool ok; int r = json.toInt(&ok); if (!ok) return INT_MIN; + return r; } diff --git a/src/widget/form/addfriendform.cpp b/src/widget/form/addfriendform.cpp index 4c38082ce..a6f229ef0 100644 --- a/src/widget/form/addfriendform.cpp +++ b/src/widget/form/addfriendform.cpp @@ -87,16 +87,22 @@ void AddFriendForm::onSendTriggered() { QString id = toxId.text().trimmed(); - if (id.isEmpty()) { + if (id.isEmpty()) + { GUI::showWarning(tr("Couldn't add friend"), tr("Please fill in a valid Tox ID","Tox ID of the friend you're sending a friend request to")); - } else if (ToxID::isToxId(id)) { + } + else if (ToxID::isToxId(id)) + { if (id.toUpper() == Core::getInstance()->getSelfId().toString().toUpper()) GUI::showWarning(tr("Couldn't add friend"), tr("You can't add yourself as a friend!","When trying to add your own Tox ID as friend")); else emit friendRequested(id, getMessage()); + this->toxId.clear(); this->message.clear(); - } else { + } + else + { if (Settings::getInstance().getProxyType() != ProxyType::ptNone) { QMessageBox::StandardButton btn = QMessageBox::warning(main, "qTox", tr("qTox needs to use the Tox DNS, but can't do it through a proxy.\n\ @@ -123,7 +129,8 @@ void AddFriendForm::setIdFromClipboard() { QClipboard* clipboard = QApplication::clipboard(); QString id = clipboard->text().trimmed(); - if (Core::getInstance()->isReady() && !id.isEmpty() && ToxID::isToxId(id)) { + if (Core::getInstance()->isReady() && !id.isEmpty() && ToxID::isToxId(id)) + { if (!ToxID::fromString(id).isMine()) toxId.setText(id); } diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index c0abf3919..5cc0b1375 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -157,6 +157,7 @@ void ChatForm::onTextEditChanged() { if (isTyping) Core::getInstance()->sendTyping(f->getFriendID(), false); + isTyping = false; return; } @@ -178,6 +179,7 @@ void ChatForm::onAttachClicked() QStringList paths = QFileDialog::getOpenFileNames(0,tr("Send a file")); if (paths.isEmpty()) return; + for (QString path : paths) { QFile file(path); @@ -269,6 +271,7 @@ void ChatForm::onAvInvite(uint32_t FriendId, int CallId, bool video) callConfirm = new CallConfirmWidget(videoButton); if (isVisible()) callConfirm->show(); + connect(callConfirm, &CallConfirmWidget::accepted, this, &ChatForm::onAnswerCallTriggered); connect(callConfirm, &CallConfirmWidget::rejected, this, &ChatForm::onRejectCallTriggered); @@ -283,6 +286,7 @@ void ChatForm::onAvInvite(uint32_t FriendId, int CallId, bool video) callConfirm = new CallConfirmWidget(callButton); if (isVisible()) callConfirm->show(); + connect(callConfirm, &CallConfirmWidget::accepted, this, &ChatForm::onAnswerCallTriggered); connect(callConfirm, &CallConfirmWidget::rejected, this, &ChatForm::onRejectCallTriggered); @@ -534,13 +538,9 @@ void ChatForm::onAvMediaChange(uint32_t FriendId, int CallId, bool video) qDebug() << "onAvMediaChange"; if (video) - { netcam->show(Core::getInstance()->getVideoSourceFromCall(CallId), f->getDisplayedName()); - } else - { netcam->hide(); - } } void ChatForm::onAnswerCallTriggered() @@ -564,10 +564,8 @@ void ChatForm::onHangupCallTriggered() //Fixes an OS X bug with ending a call while in full screen if(netcam->isFullScreen()) - { netcam->showNormal(); - } - + audioInputFlag = false; audioOutputFlag = false; emit hangupCall(callId); @@ -588,9 +586,8 @@ void ChatForm::onRejectCallTriggered() audioInputFlag = false; audioOutputFlag = false; emit rejectCall(callId); - + enableCallButtons(); - } void ChatForm::onCallTriggered() @@ -631,7 +628,7 @@ void ChatForm::onAvCallFailed(uint32_t FriendId) void ChatForm::onCancelCallTriggered() { qDebug() << "onCancelCallTriggered"; - + enableCallButtons(); netcam->hide(); @@ -806,6 +803,7 @@ void ChatForm::loadHistory(QDateTime since, bool processUndelivered) { if (earliestMessage < since) return; + if (earliestMessage < now) { now = earliestMessage; diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index 09aec7099..d6ca5a4f5 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -366,7 +366,9 @@ QString GenericChatForm::resolveToxID(const ToxID &id) if (f) { return f->getDisplayedName(); - } else { + } + else + { for (auto it : GroupList::getAllGroups()) { QString res = it->resolveToxID(id); diff --git a/src/widget/form/groupchatform.cpp b/src/widget/form/groupchatform.cpp index a12bc1cbd..3e0b93804 100644 --- a/src/widget/form/groupchatform.cpp +++ b/src/widget/form/groupchatform.cpp @@ -110,10 +110,14 @@ void GroupChatForm::onSendTriggered() emit sendAction(group->getGroupId(), msg); } else + { emit sendMessage(group->getGroupId(), msg); + } } else + { addSelfMessage(msg, msg.startsWith("/me "), QDateTime::currentDateTime(), true); + } } void GroupChatForm::onUserListChanged() @@ -150,6 +154,7 @@ void GroupChatForm::onUserListChanged() QLabel* label = orderizer[names[i]]; if (i != nNames - 1) label->setText(label->text() + ", "); + namesListLayout->addWidget(label); } diff --git a/src/widget/form/profileform.cpp b/src/widget/form/profileform.cpp index 280ac83e6..9e7cfaea3 100644 --- a/src/widget/form/profileform.cpp +++ b/src/widget/form/profileform.cpp @@ -41,6 +41,7 @@ void ProfileForm::refreshProfiles() bodyUI->profiles->clear(); for (QString profile : Settings::getInstance().searchProfiles()) bodyUI->profiles->addItem(profile); + QString current = Settings::getInstance().getCurrentProfile(); if (current != "") bodyUI->profiles->setCurrentText(current); @@ -194,6 +195,7 @@ void ProfileForm::onAvatarClicked() Nexus::getSupportedImageFilter()); if (filename.isEmpty()) return; + QFile file(filename); file.open(QIODevice::ReadOnly); if (!file.isOpen()) @@ -254,6 +256,7 @@ void ProfileForm::onRenameClicked() Settings::getInstance().setCurrentProfile(name); if (resetAutorun) Settings::getInstance().setAutorun(true); // fixes -p flag in autostart command line + break; } } while (true); diff --git a/src/widget/form/settings/generalform.cpp b/src/widget/form/settings/generalform.cpp index c1b26fcd8..e97589c44 100644 --- a/src/widget/form/settings/generalform.cpp +++ b/src/widget/form/settings/generalform.cpp @@ -52,6 +52,7 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) : bodyUI->cbEnableIPv6->setChecked(Settings::getInstance().getEnableIPv6()); for (int i = 0; i < langs.size(); i++) bodyUI->transComboBox->insertItem(i, langs[i]); + bodyUI->transComboBox->setCurrentIndex(locales.indexOf(Settings::getInstance().getTranslation())); bodyUI->cbAutorun->setChecked(Settings::getInstance().getAutorun()); #if defined(__APPLE__) && defined(__MACH__) @@ -69,7 +70,7 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) : bodyUI->minimizeToTray->setEnabled(showSystemTray); bodyUI->lightTrayIcon->setChecked(Settings::getInstance().getLightTrayIcon()); bodyUI->lightTrayIcon->setEnabled(showSystemTray); - + bodyUI->statusChanges->setChecked(Settings::getInstance().getStatusChangeNotificationEnabled()); bodyUI->useEmoticons->setChecked(Settings::getInstance().getUseEmoticons()); bodyUI->autoacceptFiles->setChecked(Settings::getInstance().getAutoSaveEnabled()); @@ -83,9 +84,8 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) : bodyUI->cbGroupchatPosition->setChecked(Settings::getInstance().getGroupchatPosition()); for (auto entry : SmileyPack::listSmileyPacks()) - { bodyUI->smileyPackBrowser->addItem(entry.first, entry.second); - } + bodyUI->smileyPackBrowser->setCurrentIndex(bodyUI->smileyPackBrowser->findData(Settings::getInstance().getSmileyPack())); reloadSmiles(); bodyUI->smileyPackBrowser->setEnabled(bodyUI->useEmoticons->isChecked()); @@ -99,6 +99,7 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) : for (QString color : Style::themeColorNames) bodyUI->themeColorCBox->addItem(color); + bodyUI->themeColorCBox->setCurrentIndex(Settings::getInstance().getThemeColor()); bodyUI->emoticonSize->setValue(Settings::getInstance().getEmojiFontPointSize()); @@ -174,7 +175,7 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) : connect(bodyUI->cbFauxOfflineMessaging, &QCheckBox::stateChanged, this, &GeneralForm::onFauxOfflineMessaging); connect(bodyUI->cbCompactLayout, &QCheckBox::stateChanged, this, &GeneralForm::onCompactLayout); connect(bodyUI->cbGroupchatPosition, &QCheckBox::stateChanged, this, &GeneralForm::onGroupchatPositionChanged); - + // prevent stealing mouse whell scroll // scrolling event won't be transmitted to comboboxes or qspinboxes when scrolling // you can scroll through general settings without accidentially chaning theme/skin/icons etc. @@ -331,11 +332,9 @@ void GeneralForm::onProxyAddrEdited() void GeneralForm::onProxyPortEdited(int port) { if (port > 0) - { Settings::getInstance().setProxyPort(port); - } else { + else Settings::getInstance().setProxyPort(-1); - } } void GeneralForm::onUseProxyUpdated() diff --git a/src/widget/form/settings/privacyform.cpp b/src/widget/form/settings/privacyform.cpp index 831f84b75..f2d728bab 100644 --- a/src/widget/form/settings/privacyform.cpp +++ b/src/widget/form/settings/privacyform.cpp @@ -115,8 +115,10 @@ bool PrivacyForm::setChatLogsPassword() else { if (GUI::askQuestion(tr("Old encrypted chat history", "popup title"), tr("There is currently an unused encrypted chat history, but the password you just entered doesn't match.\n\nIf you don't care about the old history, you may delete it and use the password you just entered.\nOtherwise, hit Cancel to try again.", "This happens when enabling encryption after previously \"Disabling History\""), tr("Delete"), tr("Cancel"))) + { if (GUI::askQuestion(tr("Old encrypted chat history", "popup title"), tr("Are you absolutely sure you want to lose the unused encrypted chat history?", "secondary popup"), tr("Delete"), tr("Cancel"))) haveEncHist = false; // logically this is really just a `break`, but conceptually this is more accurate + } } } while (haveEncHist); diff --git a/src/widget/form/tabcompleter.cpp b/src/widget/form/tabcompleter.cpp index c0f59f482..19001d9ff 100644 --- a/src/widget/form/tabcompleter.cpp +++ b/src/widget/form/tabcompleter.cpp @@ -54,8 +54,10 @@ void TabCompleter::buildCompletionList() QRegExp regex(QString("^[-_\\[\\]{}|`^.\\\\]*").append(QRegExp::escape(tabAbbrev)), Qt::CaseInsensitive); for (auto name : group->getPeerList()) + { if (regex.indexIn(name) > -1) completionMap[name.toLower()] = name; + } nextCompletion = completionMap.begin(); lastCompletionLength = tabAbbrev.length(); @@ -64,12 +66,14 @@ void TabCompleter::buildCompletionList() void TabCompleter::complete() { - if (!enabled) { + if (!enabled) + { buildCompletionList(); enabled = true; } - if (nextCompletion != completionMap.end()) { + if (nextCompletion != completionMap.end()) + { // clear previous completion auto cur = msgEdit->textCursor(); cur.setPosition(cur.selectionEnd()); @@ -85,13 +89,16 @@ void TabCompleter::complete() nextCompletion++; // we're completing the first word of the line - if (msgEdit->textCursor().position() == lastCompletionLength) { + if (msgEdit->textCursor().position() == lastCompletionLength) + { msgEdit->insertPlainText(nickSuffix); lastCompletionLength += nickSuffix.length(); } } - else { // we're at the end of the list -> start over again - if (!completionMap.isEmpty()) { + else + { // we're at the end of the list -> start over again + if (!completionMap.isEmpty()) + { nextCompletion = completionMap.begin(); complete(); } diff --git a/src/widget/groupwidget.cpp b/src/widget/groupwidget.cpp index ffd73b634..a6d6118e8 100644 --- a/src/widget/groupwidget.cpp +++ b/src/widget/groupwidget.cpp @@ -60,7 +60,9 @@ void GroupWidget::contextMenuEvent(QContextMenuEvent * event) if (selectedItem) { if (selectedItem == quitGroup) + { emit removeGroup(groupId); + } else if (selectedItem == setTitle) { bool ok; @@ -77,7 +79,7 @@ void GroupWidget::contextMenuEvent(QContextMenuEvent * event) * element - title, the rest of the widget stays in the same CSS as it * was on mouse over. Repainting whole widget fixes style problem.” */ - this->repaint(); + this->repaint(); } } } diff --git a/src/widget/toxsave.cpp b/src/widget/toxsave.cpp index f10b98596..d2d7e2445 100644 --- a/src/widget/toxsave.cpp +++ b/src/widget/toxsave.cpp @@ -42,9 +42,7 @@ bool handleToxSave(const QString& path) } while (!core->isReady()) - { qApp->processEvents(); - } QFileInfo info(path); if (!info.exists()) diff --git a/src/widget/toxuri.cpp b/src/widget/toxuri.cpp index dffc1f459..b87f3c390 100644 --- a/src/widget/toxuri.cpp +++ b/src/widget/toxuri.cpp @@ -51,9 +51,7 @@ bool handleToxURI(const QString &toxURI) } while (!core->isReady()) - { qApp->processEvents(); - } QString toxaddr; if (toxURI.startsWith("tox://")) diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 6c8f55ada..ce1061f79 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -72,6 +72,7 @@ bool toxActivateEventHandler(const QByteArray&) { if (!Widget::getInstance()->isActiveWindow()) Widget::getInstance()->forceShow(); + return true; } @@ -132,17 +133,17 @@ void Widget::init() ui->mainHead->layout()->setSpacing(0); ui->tooliconsZone->setStyleSheet(Style::resolve("QPushButton{background-color:@themeDark;border:none;}QPushButton:hover{background-color:@themeMediumDark;border:none;}")); - + if (QStyleFactory::keys().contains(Settings::getInstance().getStyle()) && Settings::getInstance().getStyle() != "None") { ui->mainHead->setStyle(QStyleFactory::create(Settings::getInstance().getStyle())); ui->mainContent->setStyle(QStyleFactory::create(Settings::getInstance().getStyle())); } - - ui->mainHead->setStyleSheet(Style::getStylesheet(":ui/settings/mainHead.css")); + + ui->mainHead->setStyleSheet(Style::getStylesheet(":ui/settings/mainHead.css")); ui->mainContent->setStyleSheet(Style::getStylesheet(":ui/settings/mainContent.css")); - + ui->statusHead->setStyleSheet(Style::getStylesheet(":/ui/window/statusPanel.css")); contactListWidget = new FriendListWidget(0, Settings::getInstance().getGroupchatPosition()); @@ -171,7 +172,7 @@ void Widget::init() Style::setThemeColor(Settings::getInstance().getThemeColor()); reloadTheme(); updateIcons(); - + filesForm = new FilesForm(); addFriendForm = new AddFriendForm; profileForm = new ProfileForm(); @@ -265,7 +266,9 @@ void Widget::updateIcons() QString status; if (eventIcon) + { status = "event"; + } else { status = ui->statusButton->property("status").toString(); @@ -291,6 +294,7 @@ Widget::~Widget() AutoUpdater::abortUpdates(); if (icon) icon->hide(); + hideMainForms(); delete profileForm; delete settingsWidget; @@ -313,6 +317,7 @@ Widget* Widget::getInstance() if (!instance) instance = new Widget(); + return instance; } @@ -337,9 +342,7 @@ void Widget::changeEvent(QEvent *event) if (event->type() == QEvent::WindowStateChange) { if (isMinimized() && Settings::getInstance().getMinimizeToTray()) - { this->hide(); - } } } @@ -448,7 +451,7 @@ void Widget::confirmExecutableOpen(const QFileInfo file) { return; } - + // The user wants to run this file, so make it executable and run it QFile(file.filePath()).setPermissions(file.permissions() | QFile::ExeOwner | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther); QProcess::startDetached(file.filePath()); @@ -531,13 +534,12 @@ void Widget::hideMainForms() QLayoutItem* item; while ((item = ui->mainHead->layout()->takeAt(0)) != 0) item->widget()->hide(); + while ((item = ui->mainContent->layout()->takeAt(0)) != 0) item->widget()->hide(); if (activeChatroomWidget != nullptr) - { activeChatroomWidget->setAsInactiveChatroom(); - } } void Widget::onUsernameChanged(const QString& newUsername, const QString& oldUsername) @@ -649,24 +651,21 @@ void Widget::onFriendStatusChanged(int friendId, Status status) if (isActualChange) { if (f->getStatus() == Status::Offline) - { contactListWidget->moveWidget(f->getFriendWidget(), Status::Online); - } else if (status == Status::Offline) - { contactListWidget->moveWidget(f->getFriendWidget(), Status::Offline); - } } f->setStatus(status); f->getFriendWidget()->updateStatusLight(); - + //won't print the message if there were no messages before if (!f->getChatForm()->isEmpty() && Settings::getInstance().getStatusChangeNotificationEnabled()) { QString fStatus = ""; - switch(f->getStatus()){ + switch(f->getStatus()) + { case Status::Away: fStatus = tr("away", "contact status"); break; case Status::Busy: @@ -716,9 +715,8 @@ void Widget::onChatroomWidgetClicked(GenericChatroomWidget *widget) hideMainForms(); widget->setChatForm(*ui); if (activeChatroomWidget != nullptr) - { activeChatroomWidget->setAsInactiveChatroom(); - } + activeChatroomWidget = widget; widget->setAsActiveChatroom(); setWindowTitle(widget->getName()); @@ -757,6 +755,7 @@ void Widget::newMessageAlert(GenericChatroomWidget* chat) bool inactiveWindow = isMinimized() || !isActiveWindow(); if (!inactiveWindow && activeChatroomWidget != nullptr && chat == activeChatroomWidget) return; + if (ui->statusButton->property("status").toString() == "busy") return; @@ -792,6 +791,7 @@ void Widget::playRingtone() { if (ui->statusButton->property("status").toString() == "busy") return; + QApplication::alert(this); static QFile sndFile1(":audio/ToxicIncomingCall.pcm"); // for whatever reason this plays slower/downshifted from what any other program plays the file as... but whatever @@ -932,7 +932,9 @@ void Widget::onGroupNamelistChanged(int groupnumber, int peernumber, uint8_t Cha // g->getChatForm()->addSystemInfoMessage(tr("%1 has left the chat").arg(name), "white", QDateTime::currentDateTime()); } else if (change == TOX_CHAT_CHANGE_PEER_NAME) // core overwrites old name before telling us it changed... + { g->updatePeer(peernumber,Nexus::getCore()->getGroupPeerName(groupnumber, peernumber)); + } } void Widget::onGroupTitleChanged(int groupnumber, const QString& author, const QString& title) @@ -1064,7 +1066,9 @@ void Widget::onUserAwayCheck() } } else if (autoAwayActive) + { autoAwayActive = false; + } #endif } @@ -1107,10 +1111,14 @@ void Widget::onTryCreateTrayIcon() setHidden(Settings::getInstance().getAutostartInTray()); } else + { show(); + } } else if (!isVisible()) + { show(); + } } else { @@ -1163,6 +1171,7 @@ void Widget::onFriendTypingChanged(int friendId, bool isTyping) Friend* f = FriendList::findFriend(friendId); if (!f) return; + f->getChatForm()->setFriendTyping(isTyping); } @@ -1196,9 +1205,7 @@ void Widget::processOfflineMsgs() { QList frnds = FriendList::getAllFriends(); for (Friend *f : frnds) - { f->getChatForm()->getOfflineMsgEngine()->deliverOfflineMsgs(); - } OfflineMsgEngine::globalMutex.unlock(); } @@ -1208,9 +1215,7 @@ void Widget::clearAllReceipts() { QList frnds = FriendList::getAllFriends(); for (Friend *f : frnds) - { f->getChatForm()->getOfflineMsgEngine()->removeAllReciepts(); - } } void Widget::reloadTheme() From 13d98da1bcd5bc1e78895ec981f01b4196c66a40 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 15:57:01 +0200 Subject: [PATCH 18/51] Correctly separate received actions from messages --- src/core/core.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 4e915dcdf..8b7784b16 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -433,8 +433,8 @@ void Core::onFriendRequest(Tox*/* tox*/, const uint8_t* cUserId, void Core::onFriendMessage(Tox*/* tox*/, uint32_t friendId, TOX_MESSAGE_TYPE type, const uint8_t* cMessage, size_t cMessageSize, void* core) { - /// TODO: Emit action or message depending on type - emit static_cast(core)->friendMessageReceived(friendId,CString::toString(cMessage, cMessageSize), false); + bool isAction = (type == TOX_MESSAGE_TYPE_ACTION); + emit static_cast(core)->friendMessageReceived(friendId,CString::toString(cMessage, cMessageSize), isAction); } void Core::onFriendNameChange(Tox*/* tox*/, uint32_t friendId, From bbf75aefb95817ffe9f685c278ce6051c9d185f6 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 18:53:19 +0200 Subject: [PATCH 19/51] Profile locking --- qtox.pro | 2 ++ src/core/core.cpp | 14 ++++++++- src/main.cpp | 8 +++++ src/profilelocker.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++ src/profilelocker.h | 40 +++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 src/profilelocker.cpp create mode 100644 src/profilelocker.h diff --git a/qtox.pro b/qtox.pro index 51506030d..2856df7d4 100644 --- a/qtox.pro +++ b/qtox.pro @@ -430,6 +430,7 @@ SOURCES += \ src/core/coreencryption.cpp \ src/core/corefile.cpp \ src/core/corestructs.cpp \ + src/profilelocker.cpp HEADERS += \ src/audio.h \ @@ -454,3 +455,4 @@ HEADERS += \ src/widget/gui.h \ src/toxme.h \ src/misc/qrwidget.h \ + src/profilelocker.h diff --git a/src/core/core.cpp b/src/core/core.cpp index 8b7784b16..56f760bc6 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -22,6 +22,7 @@ #include "src/widget/gui.h" #include "src/historykeeper.h" #include "src/audio.h" +#include "src/profilelocker.h" #include "corefile.h" #include @@ -884,6 +885,17 @@ QByteArray Core::loadToxSave(QString path) QByteArray data; loadPath = ""; // if not empty upon return, then user forgot a password and is switching + // If we can't get a lock, then another instance is already using that profile + while (!ProfileLocker::lock(QFileInfo(path).baseName())) + { + qWarning() << "Profile "< #include #include @@ -213,6 +214,13 @@ int main(int argc, char *argv[]) ipc.registerEventHandler("save", &toxSaveEventHandler); ipc.registerEventHandler("activate", &toxActivateEventHandler); + // If we're the IPC owner and we just started, then + // either we're the only running instance or any other instance + // is already so frozen it lost ownership. + // It's safe to remove any potential stale locks in this situation. + if (ipc.isCurrentOwner()) + ProfileLocker::clearAllLocks(); + if (parser.positionalArguments().size() > 0) { QString firstParam(parser.positionalArguments()[0]); diff --git a/src/profilelocker.cpp b/src/profilelocker.cpp new file mode 100644 index 000000000..4014f0d2f --- /dev/null +++ b/src/profilelocker.cpp @@ -0,0 +1,69 @@ +#include "profilelocker.h" +#include "src/misc/settings.h" +#include +#include + +using namespace std; + +unique_ptr ProfileLocker::lockfile; +QString ProfileLocker::curLockName; + +QString ProfileLocker::lockPathFromName(const QString& name) +{ + return Settings::getInstance().getSettingsDirPath()+'/'+name+".lock"; +} + +bool ProfileLocker::isLockable(QString profile) +{ + // If we already have the lock, it's definitely lockable + if (lockfile && curLockName == profile) + return true; + + QLockFile newLock(lockPathFromName(profile)); + return newLock.tryLock(); +} + +bool ProfileLocker::lock(QString profile) +{ + if (lockfile && curLockName == profile) + return true; + + QLockFile* newLock = new QLockFile(lockPathFromName(profile)); + if (!newLock->tryLock()) + { + delete newLock; + return false; + } + + unlock(); + lockfile.reset(newLock); + curLockName = profile; + return true; +} + +void ProfileLocker::unlock() +{ + if (!lockfile) + return; + lockfile->unlock(); + delete lockfile.release(); + lockfile = nullptr; + curLockName.clear(); +} + +void ProfileLocker::clearAllLocks() +{ + qDebug() << "ProfileLocker::clearAllLocks: Wiping out all lock files"; + if (lockfile) + unlock(); + + QDir dir(Settings::getInstance().getSettingsDirPath()); + dir.setFilter(QDir::Files); + dir.setNameFilters({"*.lock"}); + QFileInfoList files = dir.entryInfoList(); + for (QFileInfo fileInfo : files) + { + QFile file(fileInfo.absoluteFilePath()); + file.remove(); + } +} diff --git a/src/profilelocker.h b/src/profilelocker.h new file mode 100644 index 000000000..72ce1b93f --- /dev/null +++ b/src/profilelocker.h @@ -0,0 +1,40 @@ +#ifndef PROFILELOCKER_H +#define PROFILELOCKER_H + +#include +#include + +/// Locks a Tox profile so that multiple instances can not use the same profile. +/// Only one lock can be acquired at the same time, which means +/// that there is little need for manually unlocking. +/// The current lock will expire if you exit or acquire a new one. +class ProfileLocker +{ +private: + ProfileLocker()=delete; + +public: + /// Checks if a profile is currently locked by *another* instance + /// If we own the lock, we consider it lockable + /// There is no guarantee that the result will still be valid by the + /// time it is returned, this is provided on a best effort basis + static bool isLockable(QString profile); + /// Tries to acquire the lock on a profile, will not block + /// Returns true if we already own the lock + static bool lock(QString profile); + /// Releases the lock on the current profile + static void unlock(); + /// Releases all locks on all profiles + /// DO NOT call unless all we're the only qTox instance + /// and we don't hold any lock yet. + static void clearAllLocks(); + +private: + static QString lockPathFromName(const QString& name); + +private: + static std::unique_ptr lockfile; + static QString curLockName; +}; + +#endif // PROFILELOCKER_H From 73bd5a656fe4f555ac7aeb21c02e2685eafd1d80 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 18:54:52 +0200 Subject: [PATCH 20/51] Fix possible profile corruption When loading an encrypted profile, not entering the password and switching directly to a plaintext profile could have overwritten the plaintext profile with the encrypted one --- src/core/core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 8b7784b16..bf6772882 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -913,9 +913,9 @@ QByteArray Core::loadToxSave(QString path) if (!profile.isEmpty()) { - loadPath = QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT); Settings::getInstance().switchProfile(profile); HistoryKeeper::resetInstance(); + return loadToxSave(QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT)); } return QByteArray(); } From ea417d36882a87906c0c4281008d5255c92c625a Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 19:19:01 +0200 Subject: [PATCH 21/51] Update lock when renaming profile --- src/widget/form/profileform.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/widget/form/profileform.cpp b/src/widget/form/profileform.cpp index 9e7cfaea3..938e98799 100644 --- a/src/widget/form/profileform.cpp +++ b/src/widget/form/profileform.cpp @@ -27,6 +27,7 @@ #include "src/widget/gui.h" #include "src/historykeeper.h" #include "src/misc/style.h" +#include "src/profilelocker.h" #include #include #include @@ -247,6 +248,13 @@ void ProfileForm::onRenameClicked() if (!QFile::exists(file) || GUI::askQuestion(tr("Profile already exists", "rename confirm title"), tr("A profile named \"%1\" already exists. Do you want to erase it?", "rename confirm text").arg(cur))) { + if (!ProfileLocker::lock(name)) + { + GUI::showWarning(tr("Profile already exists", "rename failed title"), + tr("A profile named \"%1\" already exists and is in use.").arg(cur)); + break; + } + QFile::rename(dir.filePath(cur+Core::TOX_EXT), file); QFile::rename(dir.filePath(cur+".ini"), dir.filePath(name+".ini")); bodyUI->profiles->setItemText(bodyUI->profiles->currentIndex(), name); From 0baba7abe28d5cb2027006d6991ca36f4324dbf1 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 19:35:06 +0200 Subject: [PATCH 22/51] qtox.ini shouldn't overwrite our current profile If we're running on a given profile, reload the qtox.ini, and it has a diffeent value for the current profile, we don't overwrite our current value with whatever qtox.ini says anymore It would cause current profile confusions when multiple qTox instances where using different instances but sharing the qtox.ini --- src/misc/settings.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/misc/settings.cpp b/src/misc/settings.cpp index c02a406c0..996d9f039 100644 --- a/src/misc/settings.cpp +++ b/src/misc/settings.cpp @@ -215,8 +215,11 @@ void Settings::load() setProxyType(s.value("proxyType", static_cast(ProxyType::ptNone)).toInt()); proxyAddr = s.value("proxyAddr", "").toString(); proxyPort = s.value("proxyPort", 0).toInt(); - currentProfile = s.value("currentProfile", "").toString(); - currentProfileId = makeProfileId(currentProfile); + if (currentProfile.isEmpty()) + { + currentProfile = s.value("currentProfile", "").toString(); + currentProfileId = makeProfileId(currentProfile); + } autoAwayTime = s.value("autoAwayTime", 10).toInt(); checkUpdates = s.value("checkUpdates", false).toBool(); showWindow = s.value("showWindow", true).toBool(); From 05b6f1985d70a050152223a84a8de11f7badec66 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 19:43:39 +0200 Subject: [PATCH 23/51] Allow to start multiple instances with -p Starting a new instance with the -p option will force it to start a new instance with the given profile instead of bringing an eventual existing instance to the foreground Two instances can not run with the same profiles, the profile locking code will ensure that. A user who likes to live dangerously could manually delete the lock to force two instances on the same profile, but such an hypothetical user would be asking for it. If a qTox instance starts and becomes owner of the IPC shared memory on its first try, it considers itself the only running freshly-started instance, and deletes any possibly stale lock before starting up. This should be fine in the vast majority of cases, but if an existing qTox instance freezes for a long enough time to lose ownership of the IPC and a new instance is started without first killing the frozen one, the frozen instance's lock will be deleted as stale by the new one. If the frozen instance subsequentely unfreezes, it will be running on a profile for which it doesn't have a lock, which could cause trouble. This is an intentionaly allowed edge case, the alternative being a stale lock staying forever until removed manually. A potential solution not yet implemented would be to check that the lock is still actually present before attempting any write. --- src/core/core.cpp | 16 ++++++++++++++-- src/main.cpp | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 56f760bc6..39af5cd59 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -893,7 +893,8 @@ QByteArray Core::loadToxSave(QString path) tr("Your profile is already used by another qTox\n" "Please select another profile")); path = Settings::getInstance().askProfiles(); - qWarning() << "New profile is "< Date: Fri, 24 Apr 2015 20:45:26 +0200 Subject: [PATCH 24/51] Correctly rename and lock imported profiles Imported profiles are legact 'data' and 'tox_save' files --- src/main.cpp | 2 ++ src/misc/settings.cpp | 28 ++++++++++++++++++++++++++-- src/misc/settings.h | 3 +++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index abf999c01..9b9ceb4ab 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -83,6 +83,8 @@ int main(int argc, char *argv[]) a.setAttribute(Qt::AA_UseHighDpiPixmaps, true); #endif + qsrand(time(0)); + // Process arguments QCommandLineParser parser; parser.setApplicationDescription("qTox, version: " + QString(GIT_VERSION) + "\nBuilt: " + __TIME__ + " " + __DATE__); diff --git a/src/misc/settings.cpp b/src/misc/settings.cpp index 996d9f039..390d6036c 100644 --- a/src/misc/settings.cpp +++ b/src/misc/settings.cpp @@ -20,6 +20,7 @@ #include "src/misc/db/plaindb.h" #include "src/core/core.h" #include "src/widget/gui.h" +#include "src/profilelocker.h" #ifdef QTOX_PLATFORM_EXT #include "src/platform/autorun.h" #endif @@ -71,6 +72,19 @@ void Settings::switchProfile(const QString& profile) load(); } +QString Settings::genRandomProfileName() +{ + QDir dir(getSettingsDirPath()); + QString basename = "imported_"; + QString randname; + do { + randname = QString().setNum(qrand()*qrand()*qrand(), 16); + randname.truncate(6); + randname = basename + randname; + } while (QFile(dir.filePath(randname)).exists()); + return randname; +} + QString Settings::detectProfile() { QDir dir(getSettingsDirPath()); @@ -85,9 +99,19 @@ QString Settings::detectProfile() path = dir.filePath(Core::CONFIG_FILE_NAME); QFile file(path); if (file.exists()) - return path; + { + profile = genRandomProfileName(); + setCurrentProfile(profile); + file.rename(profile + Core::TOX_EXT); + return profile; + } else if (QFile(path = dir.filePath("tox_save")).exists()) // also import tox_save if no data - return path; + { + profile = genRandomProfileName(); + setCurrentProfile(profile); + QFile(path).rename(profile + Core::TOX_EXT); + return profile; + } else #endif { diff --git a/src/misc/settings.h b/src/misc/settings.h index f5c79cd21..131fd70d3 100644 --- a/src/misc/settings.h +++ b/src/misc/settings.h @@ -256,6 +256,9 @@ public: void save(QString path, bool writePersonal = true); void load(); +private: + static QString genRandomProfileName(); + private: static Settings* settings; From 42d7a7bcef16a16ec77a84be31ea5d1ff86bdeff Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 21:05:19 +0200 Subject: [PATCH 25/51] Assert profile locks before writing This fixes the potential edge case where a frozen then unfrozen qTox instance could have its locks delete by a new qTox instance. We now check that we still own our locks, restoring them if we can, before saving --- src/core/core.cpp | 2 ++ src/profilelocker.cpp | 30 ++++++++++++++++++++++++++++++ src/profilelocker.h | 6 ++++++ 3 files changed, 38 insertions(+) diff --git a/src/core/core.cpp b/src/core/core.cpp index 39af5cd59..d265db96b 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -947,6 +947,8 @@ void Core::saveConfiguration() if (!isReady()) return; + ProfileLocker::assertLock(); + QString dir = Settings::getSettingsDirPath(); QDir directory(dir); if (!directory.exists() && !directory.mkpath(directory.absolutePath())) diff --git a/src/profilelocker.cpp b/src/profilelocker.cpp index 4014f0d2f..b033410c4 100644 --- a/src/profilelocker.cpp +++ b/src/profilelocker.cpp @@ -67,3 +67,33 @@ void ProfileLocker::clearAllLocks() file.remove(); } } + +void ProfileLocker::assertLock() +{ + if (!lockfile) + { + qCritical() << "ProfileLocker::assertLock: We don't seem to own any lock!"; + deathByBrokenLock(); + } + + if (!QFile(lockPathFromName(curLockName)).exists()) + { + QString tmp = curLockName; + unlock(); + if (lock(tmp)) + { + qCritical() << "ProfileLocker::assertLock: Lock file was lost, but could be restored"; + } + else + { + qCritical() << "ProfileLocker::assertLock: Lock file was lost, and could *NOT* be restored"; + deathByBrokenLock(); + } + } +} + +void ProfileLocker::deathByBrokenLock() +{ + qCritical() << "ProfileLocker: Lock is *BROKEN*, exiting immediately"; + abort(); +} diff --git a/src/profilelocker.h b/src/profilelocker.h index 72ce1b93f..be59f043f 100644 --- a/src/profilelocker.h +++ b/src/profilelocker.h @@ -28,9 +28,15 @@ public: /// DO NOT call unless all we're the only qTox instance /// and we don't hold any lock yet. static void clearAllLocks(); + /// Check that we actually own the lock + /// In case the file was deleted on disk, restore it + /// If we can't get a lock, exit qTox immediately + /// If we never had a lock in the firt place, exit immediately + static void assertLock(); private: static QString lockPathFromName(const QString& name); + static void deathByBrokenLock(); ///< Print an error then exit immediately private: static std::unique_ptr lockfile; From 5662120c51b688b5d309124efb403326fae1ce26 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 21:34:24 +0200 Subject: [PATCH 26/51] Show Tox ID instead of blank names --- src/core/core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index d265db96b..ebe45087d 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -1035,7 +1035,7 @@ void Core::loadFriends() emit friendAdded(ids[i], CUserId::toString(clientId)); const size_t nameSize = tox_friend_get_name_size(tox, ids[i], nullptr); - if (nameSize != SIZE_MAX) + if (nameSize && nameSize != SIZE_MAX) { uint8_t *name = new uint8_t[nameSize]; if (tox_friend_get_name(tox, ids[i], name, nullptr)) From 11883bab855fdbd384c5f3533495928c967b093e Mon Sep 17 00:00:00 2001 From: Yuri Date: Thu, 26 Mar 2015 16:10:32 -0700 Subject: [PATCH 27/51] Added Ctrl+Q shortcut. --- src/widget/widget.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index ce1061f79..00a22af62 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -197,6 +198,9 @@ void Widget::init() connect(timer, &QTimer::timeout, this, &Widget::onTryCreateTrayIcon); connect(offlineMsgTimer, &QTimer::timeout, this, &Widget::processOfflineMsgs); + // keyboard shortcuts + new QShortcut(Qt::CTRL + Qt::Key_Q, this, SLOT(close())); + addFriendForm->show(*ui); connect(settingsWidget, &SettingsWidget::groupchatPositionToggled, contactListWidget, &FriendListWidget::onGroupchatPositionChanged); From 137d1ae2d5c9bee94f770f6c902194c9af34b397 Mon Sep 17 00:00:00 2001 From: PKEv Date: Sat, 28 Mar 2015 21:16:58 +0300 Subject: [PATCH 28/51] Add tooltip in filetransferwidget It is not clear what they are doing buttons --- src/chatlog/content/filetransferwidget.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/chatlog/content/filetransferwidget.cpp b/src/chatlog/content/filetransferwidget.cpp index b6a35d0b8..3ff761823 100644 --- a/src/chatlog/content/filetransferwidget.cpp +++ b/src/chatlog/content/filetransferwidget.cpp @@ -347,10 +347,12 @@ void FileTransferWidget::onFileTransferFinished(ToxFile file) ui->topButton->setIcon(QIcon(":/ui/fileTransferInstance/yes.svg")); ui->topButton->setObjectName("ok"); + ui->topButton->setToolTip(tr("Open file.")); ui->topButton->show(); ui->bottomButton->setIcon(QIcon(":/ui/fileTransferInstance/dir.svg")); ui->bottomButton->setObjectName("dir"); + ui->bottomButton->setToolTip(tr("Open file directory.")); ui->bottomButton->show(); // preview @@ -395,9 +397,11 @@ void FileTransferWidget::setupButtons() case ToxFile::TRANSMITTING: ui->topButton->setIcon(QIcon(":/ui/fileTransferInstance/no.svg")); ui->topButton->setObjectName("cancel"); + ui->topButton->setToolTip(tr("Cancel transmit.")); ui->bottomButton->setIcon(QIcon(":/ui/fileTransferInstance/pause.svg")); ui->bottomButton->setObjectName("pause"); + ui->bottomButton->setToolTip(tr("Pause transmit.")); setButtonColor(Style::getColor(Style::Green)); @@ -405,9 +409,11 @@ void FileTransferWidget::setupButtons() case ToxFile::PAUSED: ui->topButton->setIcon(QIcon(":/ui/fileTransferInstance/no.svg")); ui->topButton->setObjectName("cancel"); + ui->topButton->setToolTip(tr("Cancel transmit.")); ui->bottomButton->setIcon(QIcon(":/ui/fileTransferInstance/arrow_white.svg")); ui->bottomButton->setObjectName("resume"); + ui->bottomButton->setToolTip(tr("Resume transmit.")); setButtonColor(Style::getColor(Style::LightGrey)); @@ -416,16 +422,19 @@ void FileTransferWidget::setupButtons() case ToxFile::BROKEN: //TODO: ? ui->topButton->setIcon(QIcon(":/ui/fileTransferInstance/no.svg")); ui->topButton->setObjectName("cancel"); + ui->topButton->setToolTip(tr("Cancel transmit.")); if(fileInfo.direction == ToxFile::SENDING) { ui->bottomButton->setIcon(QIcon(":/ui/fileTransferInstance/pause.svg")); ui->bottomButton->setObjectName("pause"); + ui->bottomButton->setToolTip(tr("Pause transmit.")); } else { ui->bottomButton->setIcon(QIcon(":/ui/fileTransferInstance/yes.svg")); ui->bottomButton->setObjectName("accept"); + ui->bottomButton->setToolTip(tr("Accept transmit")); } break; } From 110a6ca850a98dc238036db8187fb464c17105e8 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 21:51:25 +0200 Subject: [PATCH 29/51] Fix typos in tooltips transmit -> tranfer --- src/chatlog/content/filetransferwidget.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/chatlog/content/filetransferwidget.cpp b/src/chatlog/content/filetransferwidget.cpp index 3ff761823..636874fd3 100644 --- a/src/chatlog/content/filetransferwidget.cpp +++ b/src/chatlog/content/filetransferwidget.cpp @@ -397,11 +397,11 @@ void FileTransferWidget::setupButtons() case ToxFile::TRANSMITTING: ui->topButton->setIcon(QIcon(":/ui/fileTransferInstance/no.svg")); ui->topButton->setObjectName("cancel"); - ui->topButton->setToolTip(tr("Cancel transmit.")); + ui->topButton->setToolTip(tr("Cancel transfer")); ui->bottomButton->setIcon(QIcon(":/ui/fileTransferInstance/pause.svg")); ui->bottomButton->setObjectName("pause"); - ui->bottomButton->setToolTip(tr("Pause transmit.")); + ui->bottomButton->setToolTip(tr("Pause transfer")); setButtonColor(Style::getColor(Style::Green)); @@ -409,11 +409,11 @@ void FileTransferWidget::setupButtons() case ToxFile::PAUSED: ui->topButton->setIcon(QIcon(":/ui/fileTransferInstance/no.svg")); ui->topButton->setObjectName("cancel"); - ui->topButton->setToolTip(tr("Cancel transmit.")); + ui->topButton->setToolTip(tr("Cancel transfer")); ui->bottomButton->setIcon(QIcon(":/ui/fileTransferInstance/arrow_white.svg")); ui->bottomButton->setObjectName("resume"); - ui->bottomButton->setToolTip(tr("Resume transmit.")); + ui->bottomButton->setToolTip(tr("Resume transfer")); setButtonColor(Style::getColor(Style::LightGrey)); @@ -422,19 +422,19 @@ void FileTransferWidget::setupButtons() case ToxFile::BROKEN: //TODO: ? ui->topButton->setIcon(QIcon(":/ui/fileTransferInstance/no.svg")); ui->topButton->setObjectName("cancel"); - ui->topButton->setToolTip(tr("Cancel transmit.")); + ui->topButton->setToolTip(tr("Cancel transfer")); if(fileInfo.direction == ToxFile::SENDING) { ui->bottomButton->setIcon(QIcon(":/ui/fileTransferInstance/pause.svg")); ui->bottomButton->setObjectName("pause"); - ui->bottomButton->setToolTip(tr("Pause transmit.")); + ui->bottomButton->setToolTip(tr("Pause transfer")); } else { ui->bottomButton->setIcon(QIcon(":/ui/fileTransferInstance/yes.svg")); ui->bottomButton->setObjectName("accept"); - ui->bottomButton->setToolTip(tr("Accept transmit")); + ui->bottomButton->setToolTip(tr("Accept transfer")); } break; } From a677e34ca4f5bfcefa9b1a6f89dca3f7ae2df655 Mon Sep 17 00:00:00 2001 From: Rohil Surana Date: Mon, 30 Mar 2015 19:44:30 +0530 Subject: [PATCH 30/51] Removed corner border in scroll area --- ui/settings/mainContent.css | 70 +++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/ui/settings/mainContent.css b/ui/settings/mainContent.css index 49fdff15d..ca3bf2828 100644 --- a/ui/settings/mainContent.css +++ b/ui/settings/mainContent.css @@ -84,108 +84,132 @@ QScrollArea QScrollArea > QWidget > QWidget { - background: transparent; + background: transparent; } -QScrollBar:vertical { +QScrollArea::corner +{ + background: white; + border: none; +} + +QScrollBar:vertical +{ background: transparent; width: 12px; margin-top: 2px; margin-bottom: 2px; } -QScrollBar::handle:vertical { +QScrollBar::handle:vertical +{ background: #d1d1d1; min-height: 20px; border-radius: 3px; margin-left: 2px; } -QScrollBar::handle:vertical:hover { +QScrollBar::handle:vertical:hover +{ background: #e3e3e3; } -QScrollBar::handle:vertical:pressed { +QScrollBar::handle:vertical:pressed +{ background: #b1b1b1; } -QScrollBar::add-line:vertical { - background: url(":ui/chatArea/scrollBarDownArrow.svg") center; +QScrollBar::add-line:vertical +{ + background: white; height: 0px; subcontrol-position: bottom; subcontrol-origin: margin; } -QScrollBar::sub-line:vertical { - background: url(":ui/chatArea/scrollBarUpArrow.svg") center; +QScrollBar::sub-line:vertical +{ + background: white; height: 0px; subcontrol-position: top; subcontrol-origin: margin; } -QScrollBar:QScrollBar::down-arrow:vertical { +QScrollBar:QScrollBar::down-arrow:vertical +{ width: 10; height: 10px; background: white; } -QScrollBar:QScrollBar::up-arrow:vertical { +QScrollBar:QScrollBar::up-arrow:vertical +{ width: 10px; height: 10px; background: white; } -QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { +QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical +{ background: none; } -QScrollBar:horizontal { +QScrollBar:horizontal +{ background: white; height: 10px; margin: 0 2px 0 2px; } -QScrollBar::handle:horizontal { +QScrollBar::handle:horizontal +{ background: #d1d1d1; min-width: 20px; border-radius: 2px; } -QScrollBar::handle:horizontal:hover { +QScrollBar::handle:horizontal:hover +{ background: #e3e3e3; } -QScrollBar::handle:horizontal:pressed { +QScrollBar::handle:horizontal:pressed +{ background: #b1b1b1; } -QScrollBar::add-line:horizontal { - background: url(":ui/chatArea/scrollBarRightArrow.svg") center; +QScrollBar::add-line:horizontal +{ + background: white; width: 0px; subcontrol-position: right; subcontrol-origin: margin; } -QScrollBar::sub-line:horizontal { - background: url(":ui/chatArea/scrollBarLeftArrow.svg") center; +QScrollBar::sub-line:horizontal +{ + background: white; width: 0px; subcontrol-position: left; subcontrol-origin: margin; } -QScrollBar:QScrollBar::down-arrow:horizontal { +QScrollBar:QScrollBar::down-arrow:horizontal +{ width: 10; height: 10px; background: white; } -QScrollBar:QScrollBar::up-arrow:horizontal { +QScrollBar:QScrollBar::up-arrow:horizontal +{ width: 10px; height: 10px; background: white; } -QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal +{ background: none; } From b4f72b620d18c6d2ed02bf3401b14f3833dcc41c Mon Sep 17 00:00:00 2001 From: kushagra Date: Sun, 29 Mar 2015 20:06:43 +0530 Subject: [PATCH 31/51] fixes action bugs 1) action received gets modified on restart 2) sender's name is written twice if action is sent using offline messaging 3) /me is written when action is sent in groupchat having one peer 4) /me is not saved in last message variable in friendd chat --- src/chatlog/chatmessage.cpp | 2 +- src/widget/form/chatform.cpp | 56 +++++++++++++++---------------- src/widget/form/groupchatform.cpp | 9 +++-- src/widget/widget.cpp | 2 +- 4 files changed, 36 insertions(+), 33 deletions(-) diff --git a/src/chatlog/chatmessage.cpp b/src/chatlog/chatmessage.cpp index c58b3209d..0106caec6 100644 --- a/src/chatlog/chatmessage.cpp +++ b/src/chatlog/chatmessage.cpp @@ -67,7 +67,7 @@ ChatMessage::Ptr ChatMessage::createChatMessage(const QString &sender, const QSt // Note: Eliding cannot be enabled for RichText items. (QTBUG-17207) msg->addColumn(new Text(senderText, isMe ? Style::getFont(Style::BigBold) : Style::getFont(Style::Big), true, sender, type == ACTION ? actionColor : Qt::black), ColumnFormat(NAME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right)); - msg->addColumn(new Text(text, Style::getFont(Style::Big), false, type == ACTION ? QString("*%1 %2*").arg(sender, rawMessage) : rawMessage), ColumnFormat(1.0, ColumnFormat::VariableSize)); + msg->addColumn(new Text(text, Style::getFont(Style::Big), false, type == (ACTION && isMe) ? QString("%1 %2").arg(sender, rawMessage) : rawMessage), ColumnFormat(1.0, ColumnFormat::VariableSize)); msg->addColumn(new Spinner(":/ui/chatArea/spinner.svg", QSize(16, 16), 360.0/1.6), ColumnFormat(TIME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right)); if(!date.isNull()) diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 5cc0b1375..10be98b76 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -58,7 +58,7 @@ ChatForm::ChatForm(Friend* chatFriend) statusMessageLabel->setFont(Style::getFont(Style::Medium)); statusMessageLabel->setMinimumHeight(Style::getFont(Style::Medium).pixelSize()); statusMessageLabel->setTextFormat(Qt::PlainText); - + callConfirm = nullptr; offlineEngine = new OfflineMsgEngine(f); @@ -116,6 +116,8 @@ void ChatForm::onSendTriggered() if (msg.isEmpty()) return; + msgEdit->setLastMessage(msg); //set last message only when sending it + bool isAction = msg.startsWith("/me "); if (isAction) msg = msg = msg.right(msg.length() - 4); @@ -123,8 +125,6 @@ void ChatForm::onSendTriggered() QList splittedMsg = Core::splitMessage(msg, TOX_MAX_MESSAGE_LENGTH); QDateTime timestamp = QDateTime::currentDateTime(); - msgEdit->setLastMessage(msg); //set last message only when sending it - bool status = !Settings::getInstance().getFauxOfflineMessaging(); for (CString& c_msg : splittedMsg) @@ -298,7 +298,7 @@ void ChatForm::onAvInvite(uint32_t FriendId, int CallId, bool video) } callButton->style()->polish(callButton); videoButton->style()->polish(videoButton); - + insertChatMessage(ChatMessage::createChatInfoMessage(tr("%1 calling").arg(f->getDisplayedName()), ChatMessage::INFO, QDateTime::currentDateTime())); Widget* w = Widget::getInstance(); @@ -357,7 +357,7 @@ void ChatForm::onAvStart(uint32_t FriendId, int CallId, bool video) this, SLOT(onMicMuteToggle())); connect(volButton, SIGNAL(clicked()), this, SLOT(onVolMuteToggle())); - + startCounter(); } @@ -375,7 +375,7 @@ void ChatForm::onAvCancel(uint32_t FriendId, int) stopCounter(); netcam->hide(); - + addSystemInfoMessage(tr("%1 stopped calling").arg(f->getDisplayedName()), ChatMessage::INFO, QDateTime::currentDateTime()); } @@ -395,7 +395,7 @@ void ChatForm::onAvEnd(uint32_t FriendId, int) } void ChatForm::onAvRinging(uint32_t FriendId, int CallId, bool video) -{ +{ if (FriendId != f->getFriendID()) return; @@ -426,7 +426,7 @@ void ChatForm::onAvRinging(uint32_t FriendId, int CallId, bool video) connect(callButton, SIGNAL(clicked()), this, SLOT(onCancelCallTriggered())); } - + addSystemInfoMessage(tr("Calling to %1").arg(f->getDisplayedName()), ChatMessage::INFO, QDateTime::currentDateTime()); } @@ -461,7 +461,7 @@ void ChatForm::onAvStarting(uint32_t FriendId, int CallId, bool video) videoButton->setToolTip(""); connect(callButton, SIGNAL(clicked()), this, SLOT(onHangupCallTriggered())); } - + startCounter(); } @@ -477,7 +477,7 @@ void ChatForm::onAvEnding(uint32_t FriendId, int) enableCallButtons(); stopCounter(); - + netcam->hide(); } @@ -493,7 +493,7 @@ void ChatForm::onAvRequestTimeout(uint32_t FriendId, int) enableCallButtons(); stopCounter(); - + netcam->hide(); } @@ -506,10 +506,10 @@ void ChatForm::onAvPeerTimeout(uint32_t FriendId, int) delete callConfirm; callConfirm = nullptr; - + enableCallButtons(); stopCounter(); - + netcam->hide(); } @@ -524,7 +524,7 @@ void ChatForm::onAvRejected(uint32_t FriendId, int) callConfirm = nullptr; enableCallButtons(); - + insertChatMessage(ChatMessage::createChatInfoMessage(tr("Call rejected"), ChatMessage::INFO, QDateTime::currentDateTime())); netcam->hide(); @@ -586,7 +586,7 @@ void ChatForm::onRejectCallTriggered() audioInputFlag = false; audioOutputFlag = false; emit rejectCall(callId); - + enableCallButtons(); } @@ -638,19 +638,19 @@ void ChatForm::onCancelCallTriggered() void ChatForm::enableCallButtons() { qDebug() << "enableCallButtons"; - + audioInputFlag = false; audioOutputFlag = false; - + micButton->setObjectName("grey"); micButton->style()->polish(micButton); micButton->setToolTip(""); - micButton->disconnect(); + micButton->disconnect(); volButton->setObjectName("grey"); volButton->style()->polish(volButton); volButton->setToolTip(""); volButton->disconnect(); - + callButton->setObjectName("grey"); callButton->style()->polish(callButton); callButton->setToolTip(""); @@ -659,7 +659,7 @@ void ChatForm::enableCallButtons() videoButton->style()->polish(videoButton); videoButton->setToolTip(""); videoButton->disconnect(); - + if(disableCallButtonsTimer == nullptr) { disableCallButtonsTimer = new QTimer(); @@ -668,7 +668,7 @@ void ChatForm::enableCallButtons() disableCallButtonsTimer->start(1500); // 1.5sec qDebug() << "timer started!!"; } - + } void ChatForm::onEnableCallButtons() @@ -683,7 +683,7 @@ void ChatForm::onEnableCallButtons() videoButton->setObjectName("green"); videoButton->style()->polish(videoButton); videoButton->setToolTip(tr("Start video call")); - + connect(callButton, SIGNAL(clicked()), this, SLOT(onCallTriggered())); connect(videoButton, SIGNAL(clicked()), @@ -824,7 +824,7 @@ void ChatForm::loadHistory(QDateTime since, bool processUndelivered) // Show the date every new day QDateTime msgDateTime = it.timestamp.toLocalTime(); QDate msgDate = msgDateTime.date(); - + if (msgDate > lastDate) { lastDate = msgDate; @@ -860,7 +860,7 @@ void ChatForm::loadHistory(QDateTime since, bool processUndelivered) rec = Core::getInstance()->sendMessage(f->getFriendID(), msg->toString()); else rec = Core::getInstance()->sendAction(f->getFriendID(), msg->toString()); - + getOfflineMsgEngine()->registerReceipt(rec, it.id, msg); } } @@ -910,7 +910,7 @@ void ChatForm::stopCounter() callDurationTimer->stop(); callDuration->setText(""); callDuration->hide(); - + delete callDurationTimer; callDurationTimer = nullptr; } @@ -931,13 +931,13 @@ QString ChatForm::secondsToDHMS(quint32 duration) duration /= 60; int hours = (int) (duration % 24); int days = (int) (duration / 24); - + if (minutes == 0) return cD + res.sprintf("%02ds", seconds); - + if (hours == 0 && days == 0) return cD + res.sprintf("%02dm %02ds", minutes, seconds); - + if (days == 0) return cD + res.sprintf("%02dh %02dm %02ds", hours, minutes, seconds); //I assume no one will ever have call longer than ~30days diff --git a/src/widget/form/groupchatform.cpp b/src/widget/form/groupchatform.cpp index 3e0b93804..a73d5eaaa 100644 --- a/src/widget/form/groupchatform.cpp +++ b/src/widget/form/groupchatform.cpp @@ -65,14 +65,14 @@ GroupChatForm::GroupChatForm(Group* chatGroup) namesListLayout = new FlowLayout(0,5,0); QStringList names(group->getPeerList()); QLabel *l; - + for (const QString& name : names) { l = new QLabel(name); l->setTextFormat(Qt::PlainText); namesListLayout->addWidget(l); } - + headTextLayout->addWidget(nusersLabel); headTextLayout->addLayout(namesListLayout); headTextLayout->addStretch(); @@ -116,7 +116,10 @@ void GroupChatForm::onSendTriggered() } else { - addSelfMessage(msg, msg.startsWith("/me "), QDateTime::currentDateTime(), true); + if (msg.startsWith("/me ")) + addSelfMessage(msg.right(msg.length() - 4), true, QDateTime::currentDateTime(), true); + else + addSelfMessage(msg, false, QDateTime::currentDateTime(), true); } } diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 00a22af62..d4599d08d 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -737,7 +737,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 " + message : message, + HistoryKeeper::getInstance()->addChatEntry(f->getToxID().publicKey, isAction ? "/me " + f->getDisplayedName() + " " + message : message, f->getToxID().publicKey, timestamp, true); f->setEventFlag(f->getFriendWidget() != activeChatroomWidget); From 0a7c82c2cf866a6f0c7673b2136dd478fa755415 Mon Sep 17 00:00:00 2001 From: kushagra Date: Fri, 10 Apr 2015 23:52:11 +0530 Subject: [PATCH 32/51] Right clicking anywhere wont unhighlight text, fixes #1517 --- src/chatlog/chatlog.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/chatlog/chatlog.cpp b/src/chatlog/chatlog.cpp index 7a3795912..45a9a293d 100644 --- a/src/chatlog/chatlog.cpp +++ b/src/chatlog/chatlog.cpp @@ -177,33 +177,17 @@ void ChatLog::mousePressEvent(QMouseEvent* ev) { QGraphicsView::mousePressEvent(ev); - QPointF scenePos = mapToScene(ev->pos()); - if(ev->button() == Qt::LeftButton) { clickPos = ev->pos(); clearSelection(); } - - if(ev->button() == Qt::RightButton) - { - if(!isOverSelection(scenePos)) - clearSelection(); - } } void ChatLog::mouseReleaseEvent(QMouseEvent* ev) { QGraphicsView::mouseReleaseEvent(ev); - QPointF scenePos = mapToScene(ev->pos()); - - if(ev->button() == Qt::RightButton) - { - if(!isOverSelection(scenePos)) - clearSelection(); - } - selectionScrollDir = NoDirection; } From 29ea557269104ba1bc412dcec95a73d0680468ce Mon Sep 17 00:00:00 2001 From: AxP Date: Sun, 12 Apr 2015 14:23:50 +0200 Subject: [PATCH 33/51] German translation updated. --- translations/de.ts | 2166 ++++++++++++++++++++++---------------------- 1 file changed, 1067 insertions(+), 1099 deletions(-) diff --git a/translations/de.ts b/translations/de.ts index edac3b357..daad748e4 100644 --- a/translations/de.ts +++ b/translations/de.ts @@ -1,6 +1,6 @@ - + AVForm @@ -9,38 +9,40 @@ Audio/Video - + Initializing Camera... - Initialisiert Kamera... + Initialisiere Kamera... AVSettings - - Playback - Wiedergabe + + Audio Settings + Die Frage hier ist immer ob man mit Leerzeichen oder Bindestrich übersetzt. Meiner Meinung sieht das aber nicht gut aus. Toneinstellungen alternativ. + Audioeinstellungen Microphone - Mikrofon + Die englische Übersetzung erscheint mir unpassend. + Aufnahmelautstärke - - Audio Settings - Audio Einstellungen + + Playback + Wiedergabelautstärke Use slider to set volume of your speakers. - + Verwende den Schieber um die Wiedergabelautstärke anzupassen. Use slider to set volume of your microphone. WARNING: slider is not supposed to work yet. - + Verwende den Schieber um die Aufnahmelautstärke deines Mikrofons anzupassen. @@ -55,27 +57,27 @@ WARNING: slider is not supposed to work yet. Rescan audio devices - Erneut nach Audiogeräten suchen + Audiogeräte aktualisieren Filter audio - Audiofilter + Aufnahme filtern Filter sound from your microphone, so that people hearing you would get better sound. - + Die Filterung verbessert deine Sprachqualität. Video Settings - Video Einstellungen + Videoeinstellungen Resolution - Auflösung + Kameraauflösung @@ -85,7 +87,9 @@ The higher values, the better video quality your friends may get. Note though that with better video quality there is needed better internet connection. Sometimes your connection may not be good enough to handle higher video quality, which may lead to problems with video calls. - + Wähle deine Kameraauflösung. +Höhere Werte führen zu einem schärferen Bild, allerdings nimmt die Netzwerkauslastung zu. +Zu hohe Auflösungen können zu Problemen in Videokonferenzen führen. @@ -111,57 +115,68 @@ which may lead to problems with video calls. AddFriendForm - + Add Friends - Freunde hinzufügen + Einen Freund hinzufügen - + Tox ID Tox ID of the person you're sending a friend request to Tox ID - + Message The message you send in friend requests - Nachricht + Freundschaftsanfrage - + Send friend request - Freundschaftsanfrage versenden + Freundschaftsanfrage senden - - Tox me maybe? + + %1 here! Tox me maybe? Default message in friend requests if the field is left blank. Write something appropriate! - Lass uns toxen! + Hallo, +Hier ist %1! Hast du Lust dich mit mir zu unterhalten? + +Viele Grüße +%1 - + + + + Couldn't add friend + Freund konnte nicht hinzugefügt werden + + + Please fill in a valid Tox ID Tox ID of the friend you're sending a friend request to - Geben Sie bitte eine gültige Tox ID ein + Entschuldigung, das hat nicht geklappt. Bitte gib eine korrekte ID an! - + You can't add yourself as a friend! When trying to add your own Tox ID as friend - Sie können sich nicht selbst als Freund hinzufügen! + Entschuldige, aber du kannst dich nicht mit dir selbst anfreunden! - + qTox needs to use the Tox DNS, but can't do it through a proxy. Ignore the proxy and connect to the Internet directly? - qTox muss das Tox DNS nutzen, dies klappt allerdings nicht über einen Proxy. -Soll der Proxy ignoriert und eine direkte Internetverbindung genutzt werden? + qTox verwendet Tox-DNS, um eine Verbindung herzustellen, aber kann das nicht mit einem aktivierten Proxyserver. +Soll der Proxyserver ignoriert werden und eine Direktverbindung hergestellt werden? - + This Tox ID does not exist DNS error - Tox ID existiert nicht + Entschuldigung, aber diese ID existiert scheinbar nicht! @@ -169,22 +184,23 @@ Soll der Proxy ignoriert und eine direkte Internetverbindung genutzt werden? Advanced - Fortgeschritten + Erweitert FULL - very safe, slowest (recommended) - VOLL - sehr sicher, langsam (empfohlen) + Die englischen Bezeichnungen scheinen mir irreführend. Normal sollte der Fall sein der keine Probleme bereitet und empfohlen ist. + Synchron NORMAL - almost as safe as FULL, about 20% faster than FULL - NORMAL - fast so sicher wie VOLL, ca. 20% schneller + Teilweise asynchron OFF - disables all safety, when something goes wrong your history may be lost, fastest (not recommended) - AUS - keinerlei Sicherheit, geht etwas schief, kann die Historie verloren gehen, ist am schnellsten (nicht empfohlen) + Vollständig asynchron (unsicher) @@ -192,42 +208,45 @@ Soll der Proxy ignoriert und eine direkte Internetverbindung genutzt werden? Form + Nicht benötigt. Save settings to the working directory instead of the usual conf dir describes makeToxPortable checkbox - Speichert die Einstellungen im Arbeits- statt im normalen Konfigurationsverzeichnis + Wenn gesetzt werden die Benutzerdaten im Arbeitsverzeichnis gesichert Make Tox portable - Macht Tox portabel + qTox portabel machen <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">IMPORTANT NOTE</span></p><p><span style=" color:#ff0000;">Unless you </span><span style=" font-weight:600; color:#ff0000;">really</span><span style=" color:#ff0000;"> know what you are doing, please do </span><span style=" font-weight:600; color:#ff0000;">not</span><span style=" color:#ff0000;"> change anything here. Changes made here may lead to problems with qTox, and even to loss of your data, e.g. history.</span></p></body></html> - <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">WICHTIGE NOTIZ</span></p><p><span style=" color:#ff0000;">Wenn Sie nicht </span><span style=" font-weight:600; color:#ff0000;">wirklich</span><span style=" color:#ff0000;"> wissen, was Sie tun, ändern Sie hier bitte </span><span style=" font-weight:600; color:#ff0000;">nichts</span><span style=" color:#ff0000;">. Hier getätigte Änderungen können zu Problemen mit qTox führen, evtl. sogar zum Datenverlust, z.B. der Historie.</span></p></body></html> + Der Html Code ist recht übertrieben und enthält Fehler. + <html> +<body style=" font-weight:400; color:#500;"> +<p>Wichtiger Hinweis:</p> +<p>Bitte beachte, dass diese Einstellungen nur geändert werden sollten, wenn du weißt was du tust! Ansonsten kann es zu Beschädigungen der Gesprächsverläufe kommen!</p> +</body> +</html> Reset to default settings - Grundeinstellungen wiederherstellen + Einstellungen zurücksetzen Chat history - - - - History - Historie + Gesprächsverlauf Einstellungen <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;">Synchrones Schreiben in die DB</span></a></p></body></html> + Datenbankverwendung @@ -235,160 +254,216 @@ Soll der Proxy ignoriert und eine direkte Internetverbindung genutzt werden? Form - + Ausgelassen + - - Your name - Ihr Name + + qTox + Ausgelassen + - - Your status - Ihr Status + + Someone + Ausgelassen + - - Add friends - Freunde hinzufügen + + Someone else + Ausgelassen + - - Create a group chat - Gruppenchat anlegen + + Groupbot + Ausgelassen + - - View completed file transfers - Vollendete Dateiübertragungen anzeigen + + That guy who I don't remember adding + Ausgelassen + - - Change your settings - Einstellungen ändern - - - - AndroidGUI - - - Online - Button to set your status to 'Online' - Online + + NASA manager + Ausgelassen + - - Away - Button to set your status to 'Away' - Abwesend + + Lorem + Ausgelassen + - - Busy - Button to set your status to 'Busy' - Beschäftigt + + Ipsum + Ausgelassen + + + + + Dolor + Ausgelassen + ChatForm - Load History... - Historie laden... + + Load chat history... + Gesprächsverlauf laden... - + Send a file Datei versenden - - + + File not read - Datei nicht gelesen + Datei nicht gesendet - - + + qTox wasn't able to open %1 - qTox konnte %1 nicht öffnen + Entschuldigung, %1 konnte nicht geöffnet werden. - - + + Bad Idea - Schlechte Idee + Datei nicht gesendet - - + + You're trying to send a special (sequential) file, that's not going to work! - Sie versuchen eine spezielle (sequentielle) Datei zu senden, das funktioniert nicht! + Entschuldigung, es ist leider nicht möglich diese Art Datei zu senden! - %1 is calling - %1 ruft an + + Accept video call + Videoanruf annehmen - - Load chat history... - + + Accept audio call + Anruf annehmen - + %1 calling - + %1 ruft an - + + + End video call + Videoanruf beenden + + + + + End audio call + Anruf beenden + + + + + Mute microphone + Mikrofon deaktivieren + + + + + Mute call + Ton deaktivieren + + + %1 stopped calling - %1 hat den Anruf beendet + %1 hat aufgelegt - + + Cancel video call + Videoanruf abbrechen + + + + Cancel audio call + Anruf abbrechen + + + Calling to %1 Rufe %1 an - + Call rejected - Anruf abgewiesen + Anruf abgelegt - + + Start audio call + Anruf starten + + + + Start video call + Videoanruf starten + + + + Unmute microphone + Mikrofon aktivieren + + + + Unmute call + Ton aktivieren + + + Failed to send file "%1" - Senden der Datei "%1" fehlgeschlagen + Entschuldigung, %1 konnte nicht gesendet werden - + Call with %1 ended. %2 - Anruf zu %1 beendet. %2 + Anruf mit %1 beendet. %2 - + Call duration: Anrufdauer: - - is typing... - tippt gerade... - ChatLog Copy - + Kopieren Select all - + Alles auswählen - + pending - + Ausstehend @@ -396,188 +471,116 @@ Soll der Proxy ignoriert und eine direkte Internetverbindung genutzt werden? Type your message here... - Nachricht hier eingeben... + Hier eine Nachricht eingeben... Core - + Toxing on qTox - Toxen mit qTox + Tox ist Toll! - + qTox User - qTox Benutzer + Mein Name - + Friend is already added - Freund wurde schon hinzugefügt + Dieser Freund wurde bereits hinzugefügt - + /me offers friendship. - + /me macht eine Freundschaftsanfrage. - + /me offers friendship, "%1" - + /me macht eine Freundschaftsanfrage, "%1" - + Encryption error - Verschlüsselungsfehler + Verschlüsselungsproblem - + The .tox file is encrypted, but encryption was not checked, continuing regardless. - Die .tox Datei ist verschlüsselt, aber die Verschlüsselung wurde nicht geprüft, Vorgang wird trotzdem fortgesetzt. - - - - Please enter the password for the %1 profile. - used in load() when no pw is already set - + Die Datendatei ist verschlüsselt, aber eine Verschlüsselung wurde nicht überprüft! - + Please enter the password for the %1 profile. + used in load() when no pw is already set + Hallo %1, +bitte gib dein Profil-Passwort ein. + + + + The previous password is incorrect; please try again: used on retries in load() - + Entschuldigung, das hat nicht geklappt. Versuch es erneut: - + The profile password failed. Please try another? used only when pw set before load() doesn't work - + Entschuldigung, das Passwort passt nicht. Versuch doch ein anderes! - + + Change profile + Profil wechseln + + + Encrypted chat history - + Verschlüsselter Gesprächsverlauf - + No encrypted chat history file found, or it was corrupted. History will be disabled! - + Entschuldige, die Verlaufsdatei wurde nicht gefunden oder ist beschädigt. +Die Verlaufsfunktion wird erst einmal ausgeschaltet! - + Please enter the password for the chat history for the %1 profile. used in load() when no hist pw set - + %1, bitte gib dein Gesprächsverlaufpasswort ein. - + Disabling chat history now will leave the encrypted history intact (but not usable); if you later remember the password, you may re-enable encryption from the Privacy tab with the correct password to use the history. part of history password dialog - + Wenn du die Verlaufsfunktion jetzt deaktivierst, wird dir die verschlüsselte Verlaufsdatei erhalten bleiben. Sollte dir später das Passwort wieder einfallen, kannst du deinen alten Verlauf weiterverwenden. - + The chat history password failed. Please try another? used only when pw set before load() doesn't work - + Entschuldigung, das Passwort für deinen Verlauf hat nicht gepasst. Versuch es erneut! - + Disable chat history - + Verlaufsfunktion deaktivieren - - Encryption is enabled, but there is no password! Encryption will be disabled. - - - - Tox datafile decryption password - Entschlüsselungspasswort für Tox Datendatei - - - Password error - Passwortfehler - - - Failed to setup password. -Empty password. - Setzen des Passwortes fehlgeschlagen. -Leeres Passwort. - - - Try Again - Nochmal versuchen - - - - Change profile - Profil ändern - - - Reinit current profile - Aktuelles Profil erneut starten - - - Wrong password has been entered - Es wurde ein falsches Passwort eingegeben - - - History Log decryption password - Passwort zur Entschlüsselung der Historie - - - Encrypted log - Verschlüsselte Logdatei - - - Your history is encrypted with different password. -Do you want to try another password? - Ihre Historie wurde mit einem anderen Passwort verschlüsselt. -Wollen Sie ein weiteres probieren? - - - Due to incorret password history will be disabled. - Falsches Passwort, Historie wird deaktiviert. - - - History - Historie - - - + NO Password - KEIN Passwort + Passwort fehlt - Will be saved without encryption! - Wird ohne Verschlüsselung gespeichert! - - - - FileTransferInstance - - Save a file - Title of the file saving dialog - Datei speichern - - - Location not writable - Title of permissions popup - Ort schreibgeschützt - - - You do not have permission to write that location. Choose another, or cancel the save dialog. - text of permissions popup - Sie haben keine Erlaubnis, die Datei in diesen Ort zu speichern. Wählen Sie einen anderen Ort oder beenden Sie den Dialog. - - - ETA - ETA + + Local file encryption is enabled, but there is no password! It will be disabled. + Die Verschlüsselung der lokalen Dateien ist aktiviert, aber es ist kein Passwort vorhanden. Die Verschlüsselung wird deswegen abgeschaltet. @@ -585,87 +588,93 @@ Wollen Sie ein weiteres probieren? Form - + Ausgelassen + 10Mb - + Ausgelassen + 0kb/s - + Ausgelassen + ETA:10:10 - + Ausgelassen + Filename - + Ausgelassen + [preview] - + Ausgelassen + - + Waiting to send... file transfer widget - + Dateitransfer läuft... - + Accept to receive this file file transfer widget - + Akzeptiere, um die Datei zu empfangen - + Location not writable Title of permissions popup - Ort schreibgeschützt + Ordner nicht beschreibbar - + You do not have permission to write that location. Choose another, or cancel the save dialog. text of permissions popup - Sie haben keine Erlaubnis, die Datei in diesen Ort zu speichern. Wählen Sie einen anderen Ort oder beenden Sie den Dialog. + Du besitzt nicht die Rechte um hier eine Datei zu speichern. Bitte wähle einen anderen Ordner oder breche die Aktion ab. - + paused file transfer widget - + Pausiert - + Save a file Title of the file saving dialog - Datei speichern + Datei speichern FilesForm - + Transfered Files "Headline" of the window Übertragene Dateien - + Downloads - Heruntergeladen + Heruntergeladene Dateien - + Uploads - Hochgeladen + Hochgeladene Dateien @@ -679,12 +688,12 @@ Wollen Sie ein weiteres probieren? Someone wants to make friends with you - Jemand möchte Ihr Freund werden + Jemand lädt dich in seine Kontaktliste ein User ID: - Benutzer ID: + ID: @@ -707,101 +716,101 @@ Wollen Sie ein weiteres probieren? FriendWidget - + Invite to group Menu to invite a friend to a groupchat - In Gruppe einladen + Gruppeneinladung - + Copy friend ID Menu to copy the Tox ID of that friend - Tox ID kopieren - - - - Set alias... - Alias setzen... + ID kopieren + Set alias... + Namen setzen... + + + Auto accept files from this friend context menu entry Dateien von diesem Freund automatisch annehmen - - Choose an auto accept directory - popup title - Wähle ein Verzeichnis für die automatische Dateiannahme - - - - User alias - Benutzeralias - - - - You can also set this by clicking the chat form name. -Alias: - Sie können diesen auch durch Klick auf den Namen des Chatfensters festlegen. -Alias: - - - + Remove friend Menu to remove the friend from our friendlist - Freund entfernen + Freund löschen + + + + Choose an auto accept directory + popup title + Speicherort angeben + + + + User alias + Nutzername + + + + You can also set this by clicking the chat form name. +Alias: + Bitte trage hier einen neuen Namen ein. +Das lässt sich auch durch einen Klick auf den Namen im Chat erreichen. GUI - + Enter your password - + Passworteingabe - + Decrypt - + Entschlüsseln - + You must enter a non-empty password: - + Du musst ein nicht-leeres Passwort angeben: GeneralForm - + General - Allgemein + Allgemeines - - + + None - Kein + Nichts - + Choose an auto accept directory popup title - Wählen Sie ein Verzeichnis + Datei-Speicherort angeben - + Call active popup title - Anwahl aktiviert + Anruf aktiv - + You can't disconnect while a call is active! popup text - Abbruch während der Anwahl nicht möglich! + Du kannst dich nicht abmelden solange ein Anruf aktiv ist! @@ -815,32 +824,7 @@ Alias: The translation may not load until qTox restarts. - Änderung wird erst nach Neustart von qTox aktiv. - - - - Show system tray icon - In der Systemleiste anzeigen - - - - Start in tray - In die Systemleiste starten - - - - Close to tray - In die Systemleiste schließen - - - - Minimize to tray - In die Systemleiste minimieren - - - - Light icon - Helles Icon + qTox muss neugestartet werden, um die Änderungen zu übernehmen. @@ -852,67 +836,113 @@ Alias: System tray Systemleiste + + + Show system tray icon + Icon in Systemleiste + Enable light tray icon. toolTip for light icon setting - + Helles Icon aktivieren. + + + + Light icon + Helles Icon qTox will start minimized in tray. toolTip for Start in tray setting - + Wenn aktiv, qTox startet minimiert. + + + + Start in tray + Im Hintergrund starten After pressing close (X) qTox will minimize to tray, instead of closing itself. toolTip for close to tray setting - + Wenn aktiv, qTox wird nicht sofort beendet, sondern in die Systemleiste minimiert. + + + + Close to tray + In Systemleiste schließen After pressing minimize (_) qTox will minimize itself to tray, instead of system taskbar. toolTip for minimize to tray setting - + Wenn aktiv, qTox wird in die Systemleiste minimiert. + + + + Minimize to tray + In Systemleiste minimieren <html><head/><body><p>Start qTox on operating system startup (current profile).</p></body></html> - + Wenn aktiv, qTox wird bei Systemstart geladen. Autostart - + Mit Betriebssystem starten Check for updates on startup - Beim Starten auf Updates überprüfen + Beim Start nach Updates suchen Set where files will be saved. - + Datei-Speicherort angeben. Save to: - Speichern in: + Speicherort: + + + + You can set this on a per-friend basis by right clicking them. + autoaccept cb tooltip + Dies lässt sich für jeden Kontakt einzeln einstellen. (Rechtsklickmenü) + + + + Autoaccept files + Dateien automatisch annehmen + + + + Set to 0 to disable + '0' deaktiviert die Funktion + + + + minutes + Minuten Your status is changed to Away after set period of inactivity. - + Nach einer Weile wird dein Status auf 'Abwesend' gesetzt. Auto away after (0 to disable): - Automatisch abwesend nach (0 zum Deaktivieren): + Automatisch abwesend nach (Aus = 0): @@ -923,236 +953,196 @@ instead of system taskbar. Always notify about new messages in groupchats. toolTip for Group chat always notify - + Immer auf neue Nachrichten in Gruppenchats hinweisen. Group chats always notify - Über Gruppenchats immer informieren + Gruppenchat Hinweise Show contacts' status changes - Zeigt Statusänderungen der Kontakte + Hinweis bei Statusänderungen + + + + On new message: + Bei neuen Nachrichten: Show qTox's window when you receive new message. tooltip for Show window setting - + Öffne qTox bei neuen Nachrichten. + + + + Show window + Öffne Chat Focus qTox when you receive message. toolTip for Focus window setting - - - - - Messages you are trying to send to your friends when they are not online -will be sent to them when they will appear online to you. - toolTip for Faux offline messaging setting - - - - - Faux offline messaging - Imitiert Offline Benachrichtigung - - - Compact contact list (restart required) - Kompakte Darstellung der Kontaktliste (Neustart benötigt) - - - Provided in minutes - Angabe in Minuten - - - Auto away after (0 to disable) - Automatisch abwesend nach (0 deaktiviert) - - - - Set to 0 to disable - Zum Deaktivieren auf 0 setzen - - - - You can set this on a per-friend basis by right clicking them. - autoaccept cb tooltip - Sie können dies durch Rechtsklick auf den jeweiligen Freund festlegen. - - - - Use emoticons - Emoticons benutzen - - - Smiley Pack - Text on smiley pack label - Emoticon Paket - - - Style - Stil - - - Theme color - Farbe - - - Emoticon size - Emoticon Größe - - - - px - Pixel - - - Timestamp format - Zeitformat - - - - Disabling this allows, e.g., toxing over Tor. It adds load to the Tox network however, so uncheck only when necessary. - force tcp checkbox tooltip - Wenn deaktiviert kann z.B. über Tor getoxt werden. Dies belastet das Tox Netzwerk zusätzlich und sollte nur deaktiviert werden wenn notwendig. - - - - Enable UDP (recommended) - Text on checkbox to disable UDP - UDP aktivieren (empfohlen) - - - - Proxy type: - Proxy Typ: - - - - Address: - Text on proxy addr label - Adresse: - - - - SOCKS5 - SOCKS5 - - - - HTTP - HTTP - - - - Reconnect - reconnect button - Erneut verbinden - - - - minutes - Minuten - - - - Autoaccept files - Dateien automatisch annehmen - - - PushButton - Schaltfläche - - - - On new message: - Bei neuer Nachricht: - - - - Show window - Zeige Fenster + Auf Fenster fokussieren, wenn neue Nachrichten eingehen. Focus window - Bringe Fenster in den Vordergrund + Fokussiere das Fenster - - Your contact list will be shown in compact mode. - toolTip for compact layout setting - + + Play a sound when you recieve message. + toolTip for Notify sound setting + Bei neuen Nachrichten einen Ton abspielen. + + + + Play sound + Spiele einen Ton ab + + + + Messages you are trying to send to your friends when they are not online +will be sent to them when they appear online to you. + toolTip for Faux offline messaging setting + Offline-Nachrichten werden übertragen, sobald der entsprechende Kontakt verfügbar wird, während du online bist. + Faux offline messaging + Pseudo-Offline Nachrichten + + + + Your contact list will be shown in compact mode. + toolTip for compact layout setting + Die Kontaktliste wird kompakter dargestellt. + + + Compact contact list Kompakte Kontaktliste - - Theme - Benutzeroberfläche + + If checked, groupchats will be placed at the top of the friends list, otherwise, they'll be placed below online friends. + toolTip for groupchat positioning + Stelle Gruppenchats über die normalen Kontakte. - + + Place groupchats at top of friend list + Gruppenchats oben + + + + Theme + Aussehen + + + + Use emoticons + Emoticons verwenden + + + Smiley Pack: Text on smiley pack label - Smiley Paket: + Smiley Art: - + Emoticon size: - Emoticon Größe: + Smileygröße: - + + px + Pixel + + + Style: - Stil: + Grundstil: - + Theme color: - Fensterfarbe: + Grundfarbe: - + Timestamp format: Zeitformat: - + + Date format: + Datumsformat: + + + Connection Settings Verbindungseinstellungen - + + Disabling this allows, e.g., toxing over Tor. It adds load to the Tox network however, so uncheck only when necessary. + force tcp checkbox tooltip + Wenn deaktiviert, lässt sich qTox mit Tor verwenden. Die Deaktivierung belastet allerdings das Tox-Netzwerk. + + + + Enable UDP (recommended) + Text on checkbox to disable UDP + UDP aktivieren (Empfohlen) + + + Enable IPv6 (recommended) Text on a checkbox to enable IPv6 - IPv6 aktivieren (empfohlen) + IPv6 aktivieren (Empfohlen) - Proxy type - Proxy Typ + + Proxy type: + Proxy-Typ: - - None - Keinen - - - Address + + Address: Text on proxy addr label - Adresse + Addresse: - + Port Text on proxy port label - Port + Port: + + + + None + Kein Proxy + + + + SOCKS5 + + + + + HTTP + + + + + Reconnect + reconnect button + Erneut verbinden @@ -1160,7 +1150,7 @@ will be sent to them when they will appear online to you. Send message - Nachricht senden + Nachricht versenden @@ -1170,382 +1160,270 @@ will be sent to them when they will appear online to you. Send file(s) - Datei(en) senden + Datei senden - Audio call: RED means you're on a call - Sprachanruf: ROT bedeutet verbunden + Start an audio call + Anruf starten - Video call: RED means you're on a call - Videoanruf: ROT bedeutet verbunden - - - - Toggle speakers volume: RED is OFF - Schaltet den Lautsprecher ein/aus: ROT ist AUS - - - - Toggle microphone: RED is OFF - Schaltet das Mikrofon ein/aus: ROT ist AUS + Start a video call + Videoanruf starten - + Save chat log - Chatverlauf speichern + Gesprächsverlauf speichern Clear displayed messages - Angezeigte Nachrichten ausblenden + Angezeigte Nachrichten entfernen - + Not sent - + Nicht gesendet - + Cleared - Ausgeblendet + Gesprächsverlauf entfernt GroupChatForm - + %1 users in chat Number of users in chat - %1 Teilnehmer im Chat + %1 Kontakte im Chat - + %1 users in chat - %1 Teilnehmer im Chat + %1 Kontakt im Chat + + + + + Start audio call + Anruf starten + + + + + Mute microphone + Mikrofon deaktivieren + + + + Unmute microphone + Mikrofon aktivieren + + + + + Mute call + Ton deaktivieren + + + + Unmute call + Ton aktivieren + + + + End audio call + Anruf beenden GroupWidget - - - - %1 users in chat - %1 Teilnehmer im Chat - - + + %1 users in chat + %1 Kontakte im Chat + + + + 0 users in chat - kein Teilnehmer im Chat + Keine Kontakte im Chat - + Set title... - Titel festlegen... + Titel wählen... - + Quit group Menu to quit a groupchat Gruppe verlassen - + Group title - Gruppentitel + Gruppenname - + You can also set this by clicking the chat form name. Title: - Sie können diesen auch durch Klick auf den Namen des Chatfensters festlegen. -Titel: - - - - IdentityForm - - - Identity - Identität - - - - Call active - popup title - Anruf aktiv - - - - You can't switch profiles while a call is active! - popup text - Das Profil kann während eines Anrufes nicht gewechselt werden! - - - - Rename "%1" - renaming a profile - "%1" umbenennen - - - - Profile already exists - rename confirm title - Profil existiert bereits - - - - A profile named "%1" already exists. Do you want to erase it? - rename confirm text - Ein Profil mit dem Namen "%1" existiert bereits. Wollen Sie es löschen? - - - - Export profile - save dialog title - Profil exportieren - - - - Tox save file (*.tox) - save dialog filter - Toxdatei speichern (*.tox) - - - - Failed to remove file - Entfernen der Datei fehlgeschlagen - - - - The file you chose to overwrite could not be removed first. - Die gewählte Datei kann nicht überschrieben werden. - - - - Failed to copy file - Kopieren der Datei fehlgeschlagen - - - - The file you chose could not be written to. - Die gewählte Datei kann nicht überschrieben werden. - - - - Profile currently loaded - current profile deletion warning title - Profil ist zurzeit geladen - - - - This profile is currently in use. Please load a different profile before deleting this one. - current profile deletion warning text - Dieses Profil ist aktuell in Gebrauch. Bitte laden Sie vor dem Löschen ein anderes Profil. - - - - Deletion imminent! - deletion confirmation title - Löschen steht bevor! - - - - Are you sure you want to delete this profile? - deletion confirmation text - - - - Are you sure you want to delete this profile? -Associated friend information and chat logs will be deleted as well. - deletion confirmation text - Wollen Sie dieses Profil wirklich löschen? -Dazugehörige Informationen und Chatprotokolle werden ebenfalls gelöscht. - - - - Import profile - import dialog title - Profil importieren - - - - Tox save file (*.tox) - import dialog filter - Toxdatei speichern (*.tox) - - - - Ignoring non-Tox file - popup title - Keine Toxdatei, wird ignoriert - - - - Warning: you've chosen a file that is not a Tox save file; ignoring. - popup text - Warnung: Sie haben eine Datei gewählt, die keine Toxdatei ist, wird ignoriert. - - - - Profile already exists - import confirm title - Profil existiert bereits - - - - A profile named "%1" already exists. Do you want to erase it? - import confirm text - Ein Profil mit dem Namen "%1" existiert bereits. Wollen Sie es löschen? + Lässt sich auch durch einen Klick auf den Name im Chat ändern. +Name: IdentitySettings - + Public Information Öffentliche Informationen - + Name - Benutzername + Dein Name - + Status - Status + Dein Status - + Tox ID - Tox ID + ID Informationen - + + This bunch of characters tells other Tox clients how to contact you. Share it with your friends to communicate. Tox ID tooltip - + Dies ist deine persönliche Addresse. Damit können dich andere qTox-Nutzer erreichen. +Teile sie einfach deinen Bekannten mit! - + Your Tox ID (click to copy) - Ihre Tox ID (klicken zum Kopieren) + Deine Tox ID (Klicken zum kopieren) - + + QRCODE + Ausgelassen + + + + + This QR code contains your Tox ID. You may share this with your friends as well. + Ein QR-Code, der deine Tox ID enthält. Dieser lässt sich anstatt der ID verwenden! + + + + Save image + Bild speichern + + + + Copy image + Bild kopieren + + + Profiles - Profile + Profil Informationen - + Available profiles: Verfügbare Profile: - + Currently selected profile. toolTip for currently set profile - + Zurzeit verwendetes Profile. - + Load selected profile and switch to it. tooltip for loading profile button - + Ausgewähltes Profil laden und verwenden. - Switching profiles is disabled during calls - tooltip - Profilwechsel ist während eines Anrufes deaktiviert - - - + Load load profile button - Laden + Profil laden - + + Rename selected profile. + tooltip for renaming profile button + Ausgewähltes Profil umbenennen. + + + Rename rename profile button Umbenennen - - Rename selected profile. - tooltip for renaming profile button - + + Allows you to export your Tox profile to a file. +Profile does not contain your history. + tooltip for profile exporting button + Speichert das ausgewählte Profil in eine Datei. Beachte, dass diese Datei deinen Gesprächsverlauf <i>nicht</i> enthält! - + Export export profile button Exportieren - - Allows you to export your Tox profile to a file. -Profile does not contain your history. - tooltip for profile exporting button - - - - + Delete selected profile. delete profile button tooltip - + Löscht das oben ausgewählte Profil. - + Delete delete profile button Löschen - + Import Tox profile from a .tox file. tooltip for importing profile button - + Importiert ein Profil in Form einer <i>*.tox</i> Datei. - - Create new Tox ID and switch to it. - tooltip for creating new Tox ID button - - - - - New Tox ID - new profile button - Neue Tox ID - - - This is useful to remain safe on public computers - delete profile button tooltip - Dies ist nützlich, um auf öffentlichen Computern sicher zu sein - - - + Import a profile import profile button - Importieren - - - - InputPasswordDialog - - Password Dialog - Passwort + Profil importieren - Input password: - Passwort eingeben: + + Create new Tox ID and switch to it. + tooltip for creating new Tox ID button + Erstellt ein neues Profil und wechselt zu diesem. + + + + New Tox ID + new profile button + Neues Profil @@ -1553,48 +1431,48 @@ Profile does not contain your history. Load History Dialog - Historie laden + Gesprächsverlauf Load history from: - Lade die Historie vom: + Den Verlauf von einem bestimmten Datum bis Heute anzeigen: MainWindow - + Your name - Ihr Name + Dein Name - + Your status - Ihr Status + Dein Status - + Add friends - Freunde hinzufügen + Einen Freund hinzufügen - + Create a group chat - Gruppenchat anlegen + Eine neue Gruppe eröffnen - + View completed file transfers - Vollendete Dateiübertragungen anzeigen + Dateiverläufe anzeigen - + Change your settings Einstellungen ändern - + Close Schließen @@ -1604,16 +1482,16 @@ Profile does not contain your history. Tox video - Tox Video + qTox Videokonferenz Nexus - + Images (%1) filetype filter - + Bilder (%1) @@ -1626,103 +1504,118 @@ Profile does not contain your history. Please set your new chat history password. - Bitte Passwort zum Verschlüsseln des Chatverlaufs setzen. + Bitte wähle ein neues Passwort für die Verschlüsselung deiner Gesprächsverläufe. It appears you have an unused encrypted chat history; if the password matches, it will be added to your current history. - Es scheint als gäbe es einen unverschlüsselten Chatverlauf. Wenn die Passwörter übereinstimmen wird dieser zum aktuellen Chatverlauf hinzugefügt. + Es scheint, dass bereits eine verschlüsselte Verlaufsdatei vorhanden ist. Sollte das angegebene Passwort passen, wird diese weiterverwendet. Use data file password pushbutton text - Nutze das Tox-Datendatei Passwort + Das Datenpasswort verwenden Successfully decrypted old chat history popup title - Alter Chatverlauf erfolgreich entschlüsselt + Der alte Verlauf wurde erfolgreich entschlüsselt You have succesfully decrypted the old chat history, and it has been added to your current history and re-encrypted. popup text - Der alte Chatverlauf wurde erfolgreich entschlüsselt, zum aktuellen Chatverlauf hinzugefügt und wieder verschlüsselt. + Die alte Verlaufsdatei wurde erfolgreich entschlüsselt und wurde in deine aktuellen Verläufe integriert. Old encrypted chat history popup title - Alter verschlüsselter Chatverlauf + Ehemalige Gesprächsverläufe There is currently an unused encrypted chat history, but the password you just entered doesn't match. -If you don't care about the old history, you may click Ok to delete it and use the password you just entered. -Otherwise, hit cancel to try again. +If you don't care about the old history, you may delete it and use the password you just entered. +Otherwise, hit Cancel to try again. This happens when enabling encryption after previously "Disabling History" - + Es ist eine ehemalige Verlaufsdatei vorhanden, allerdings passt das Passwort nicht, dass du angegeben hast. + +Wenn es dich nicht stört, kann sie gelöscht und das neue Passwort verwendet werden. +Falls doch, drücke auf Abbrechen und versuche es erneut. + + + + + + + Delete + Löschen + + + + + + + + Cancel + Abbrechen Are you absolutely sure you want to lose the unused encrypted chat history? secondary popup - + Bestätige, dass du die alten Verläufe löschen möchtest. + + + + + Old encrypted chat history + title + Ehemalige Gesprächsverläufe - - Old encrypted chat history - title - Alter verschlüsselter Chatverlauf - - - Would you like to decrypt your chat history? Otherwise it will be deleted. - Möchten Sie den Chatverlauf entschlüsseln? -Ansonsten wird dieser gelöscht. + Möchtest du deinen Gesprächsverlauf entschlüsseln oder lieber löschen? - + + + Decrypt + Entschlüsseln + + + Are you sure you want to lose your entire chat history? - Sind Sie sicher, dass der gesamte Chatverlauf gelöscht werden soll? + Bestätige, dass du deine Gesprächsverläufe löschen möchtest. - + Please set your new data file password. - Bitte Passwort zum Verschlüsseln der Datendatei setzen. + Bitte wähle ein neues Passwort für deine Daten. - + Use chat history password pushbutton text - Nutze das Chatverlauf-Passwort + Gesprächsverlauf-Passwort wiederverwenden - + Decrypt your data file title - Datendatei entschlüsseln + Datendatei entschlüsseln - + Would you like to decrypt your data file? - Möchten Sie die Datendatei entschlüsseln? - - - Encrypted log - Verschlüsselte Logdatei - - - You already have history log file encrypted with different password -Do you want to delete old history file? - Es gibt schon eine Historie Logdatei mit einem anderen Passwort. -Soll die alte Historiedatei gelöscht werden? + Bestätige, dass du deine Datendatei entschlüsseln möchtest. @@ -1731,44 +1624,55 @@ Soll die alte Historiedatei gelöscht werden? Your friends will be able to see when you are typing. tooltip for typing notifications setting - + Wenn aktiviviert, können deine Kontakte sehen, dass du tippst. Send Typing Notifications - Tippen anzeigen + Eingabehinweis senden Chat history keeping is still in development. Save format changes are possible, which may result in data loss. toolTip for Keep History setting - + Wenn aktiviert, wird der Gesprächsverlauf dauerhaft gesichert. Keep chat history (mostly stable) - Chatverlauf speichern (größtenteils stabil) + Gesprächsverläufe dauerhaft sichern Local file encryption - Lokale Dateien verschlüsseln + Verschlüsselung All Tox communications over the internet are encrypted, and this cannot be disabled. However, you may optionally password protect your local Tox files. - Die gesamte Tox-Kommunikation über das Internet ist verschlüsselt und kann auch nicht deaktiviert werden. Es ist optional auch möglich, die lokal gespeicherten Tox-Daten mit einem Passwort zu schützen. + Jegliche Kommunikation über qTox ist vollständig verschlüsselt. Diese Funktion lässt sich <i>nicht</i> deaktiviern. Darüber hinaus kannst du deine lokalen Dateien verschlüsseln. Encrypt Tox data file - Tox Datendatei verschlüsseln + Datendateien verschlüsseln + + + + + Change password + Passwort wechseln Encrypt chat history - Chatverlauf verschlüsseln + Gesprächsverläufe verschlüsseln + + + + Nospam + Störende Anfragen blockieren @@ -1777,199 +1681,300 @@ It is there to help you change your Tox ID when you feel like you are getting to 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 - - - - - - Change password - Passwort ändern - - - Please set your new chat history password. - Bitte Passwort zum Verschlüsseln des Chatverlaufs setzen. - - - It appears you have an unused encrypted chat history; if the password matches, it will be added to your current history. - Es scheint als gäbe es einen unverschlüsselten Chatverlauf. Wenn die Passwörter übereinstimmen wird dieser zum aktuellen Chatverlauf hinzugefügt. - - - Use data file password - Nutze das Tox-Datendatei Passwort - - - Successfully decrypted old chat history - Alter Chatverlauf erfolgreich entschlüsselt - - - You have succesfully decrypted the old chat history, and it has been added to your current history and re-encrypted. - Der alte Chatverlauf wurde erfolgreich entschlüsselt, zum aktuellen Chatverlauf hinzugefügt und wieder verschlüsselt. - - - Old encrypted chat history - Alter verschlüsselter Chatverlauf - - - There is currently an unused encrypted chat history, but the password you just entered doesn't match. -Would you like to try again? -Canceling will delete the old history and set the password to what you just entered. - Es gibt aktuell einen ungenutzten verschlüsselten Chatverlauf, aber das eingegebene Passwort stimmt nicht überein. -Möchten Sie ein anderes probieren? -Wenn Sie abbrechen wird der alte Chatverlauf gelöscht und das soeben eingegebene Passwort verwendet. - - - This happens when enabling encryption after previously \"Disabling History\" - Dies passiert, wenn die Verschlüsselung nach einem vorherigen Deaktivieren des Chatverlaufs wieder aktiviert wird. - - - Would you like to decrypt your chat history? -Otherwise it will be deleted. - Möchten Sie den Chatverlauf entschlüsseln? -Ansonsten wird dieser gelöscht. - - - Are you sure you want to lose your entire chat history? - Sind Sie sicher, dass der gesamte Chatverlauf gelöscht werden soll? - - - Please set your new data file password. - Bitte Passwort zum Verschlüsseln der Datendatei setzen. - - - Use chat history password - Nutze das Chatverlauf-Passwort - - - Decrypt your data file - Datendatei entschlüsseln - - - Would you like to decrypt your data file? - Möchten Sie die Datendatei entschlüsseln? - - - The passwords don't match. - Die Passwörter stimmen nicht überein. - - - - Nospam - Spam-Schutz - - - HHHHHHHH - HHHHHHHH + Dies ist ein Teil deiner ID. +Diese ID soll dabei helfen, deine Tox ID zu ändern, falls dich zu viele ungewollte Anfragen erreichen. +Deine bereits vorhandenen Kontakte können dich auch weiterhin erreichen, +nur neue Kontakte benötigen deine neue ID. Generate random nospam - Zufälligen Spam-Schutz erzeugen + ID Generieren + + + + ProfileForm + + + User Profile + Nutzerprofil + + + + Choose a profile picture + Wähle ein Profilbild + + + + + + Error + Fehler beim Öffnen + + + + Unable to open this file + Entschuldige, die ausgewählte Datei konnte nicht geöffnet werden + + + + Unable to read this image + Entschuldige, das ausgewählte Bild konnte nicht gelesen werden + + + + This image is too big + Entschuldige, dieses Bild ist leider etwas zu groß + + + + Call active + popup title + Anruf aktiv + + + + You can't switch profiles while a call is active! + popup text + Entschuldige, aber du kannst dein Profil nicht wechseln, solange ein Anfruf aktiv ist. + + + + Rename "%1" + renaming a profile + Profil '%1' umbenennen + + + + Profile already exists + rename confirm title + Profil bereits vorhanden + + + + A profile named "%1" already exists. Do you want to erase it? + rename confirm text + Entschuldige, aber ein Profil namens '%1' existiert bereits. Möchtest du es überschreiben? + + + + Export profile + save dialog title + Profil exportieren + + + + Tox save file (*.tox) + save dialog filter + Tox Datei (*.tox) + + + + + Location not writable + Title of permissions popup + Verzeichnis nicht beschreibbar + + + + + You do not have permission to write that location. Choose another, or cancel the save dialog. + text of permissions popup + Entschuldige, du scheinst nicht die nötigen Rechte zu haben, um hier eine Datei zu speichern. Wähle doch ein anderes Verzeichnis. + + + + + Failed to copy file + Kopieren fehlgeschlagen + + + + + The file you chose could not be written to. + Entschuldige, aber die gewählte Datei konnte leider nicht beschrieben werden. + + + + Profile currently loaded + current profile deletion warning title + Profil zurzeit in Verwendung + + + + This profile is currently in use. Please load a different profile before deleting this one. + current profile deletion warning text + Dieses Profil wird zurzeit verwendet. Bevor du dieses Profil löschst, solltest du ein anderes laden. + + + + Deletion imminent! + deletion confirmation title + Profil wird gelöscht + + + + Are you sure you want to delete this profile? + deletion confirmation text + Bestätige, dass du das gewählte Profil löschen möchtest. + + + + Import profile + import dialog title + Profil importieren + + + + Tox save file (*.tox) + import dialog filter + Tox Datei (*.tox) + + + + Ignoring non-Tox file + popup title + Nicht-Tox Datei ignoriert + + + + Warning: you've chosen a file that is not a Tox save file; ignoring. + popup text + Es scheint, dass du eine Datei gewählt hast, die nicht zu Tox gehört. Sie wird erst einmal ignoriert. + + + + Profile already exists + import confirm title + Profil bereits vorhanden + + + + A profile named "%1" already exists. Do you want to erase it? + import confirm text + Ein Profil mit den Namen '%1' existiert bereits. Möchtest du es löschen? + + + + Save + save qr image + Bild speichern + + + + Save QrCode (*.png) + save dialog filter + QR-Code speichern (*.png) QObject - + Update The title of a message box - Update + Aktualisieren - + An update is available, do you want to download it now? It will be installed when qTox restarts. - Ein Update steht zur Verfügung, soll es heruntergeladen werden? -Es wird beim Neustart von qTox installiert. + Eine Aktualisierung für qTox ist verfügbar! Möchtest du sie jetzt herunterladen? +Sie wird bei einem Neustart installiert. - + + Resizing + Größe ändern + + + Tox URI to parse - Tox URI parsen + Zu parsende Tox URI - + Starts new instance and loads specified profile. - Startet eine neue Instanz und lädt das festgelegte Profil. + Startet eine neue Instanz und lädt das angegebene Profil. - + profile Profil - + Default Standard - + Blue Blau - + Olive Oliv - + Red Rot - + Violet Violett - - - Ignoring non-Tox file - popup title - Keine Toxdatei, wird ignoriert - - - - Warning: you've chosen a file that is not a Tox save file; ignoring. - popup text - Warnung: Sie haben eine Datei gewählt, die keine Toxdatei ist, wird ignoriert. - - - - Profile already exists - import confirm title - Profil existiert bereits - - - - A profile named "%1" already exists. Do you want to erase it? - import confirm text - Ein Profil mit dem Namen "%1" existiert bereits. Wollen Sie es löschen? - - - - Profile imported - Profil importiert - - - - %1.tox was successfully imported - %1.tox wurde erfolgreich importiert - - - - Tox me maybe? - Default message in Tox URI friend requests. Write something appropriate! - Lass uns toxen! - Incoming call... Eingehender Anruf... - - Busy... - + + Ignoring non-Tox file + popup title + Nicht-Tox Datei ignoriert + + + + Warning: you've chosen a file that is not a Tox save file; ignoring. + popup text + Es scheint, dass du eine Datei gewählt hast, die nicht zu Tox gehört. Sie wird erst einmal ignoriert. + + + + Profile already exists + import confirm title + Profil bereits vorhanden + + + + A profile named "%1" already exists. Do you want to erase it? + import confirm text + Entschuldige, aber ein Profil namens '%1' existiert bereits. Möchtest du es überschreiben? + + + + Profile imported + Profil importiert + + + + %1.tox was successfully imported + Die Datei %1.tox wurde erfolgreich importiert + + + + %1 here! Tox me maybe? + Default message in Tox URI friend requests. Write something appropriate! + Hallo, +Hier ist %1! Hast du Lust dich mit mir zu unterhalten? + +Viele Grüße +%1 @@ -1977,41 +1982,41 @@ Es wird beim Neustart von qTox installiert. Set your password - Passwort setzen - - - - Type password - Passwort eingeben + Setze dein Passwort Repeat password - Passwort wiederholen + Wiederholen + + + + Type password + Passwort Password strength - Passwortstärke + Stärke The passwords don't match. - Die Passwörter stimmen nicht überein. + Die eingegebenen Passwörter stimmen nicht überein. Settings - + Choose a profile - Wählen Sie ein Profil + Wähle ein Profil - + Please choose which identity to use - Wählen Sie die Identität, die benutzt werden soll + Bitte wähle ein Profil aus @@ -2020,7 +2025,7 @@ Es wird beim Neustart von qTox installiert. The connection timed out The DNS gives the Tox ID associated to toxme.se addresses - Zeitlimit der Verbindung überschritten + Eine Zeitüberschreitung in der Verbindung ist aufgetreten @@ -2032,38 +2037,38 @@ Es wird beim Neustart von qTox installiert. Error while looking up DNS The DNS gives the Tox ID associated to toxme.se addresses - Fehler beim Auflösen des DNS + Beim Nachschlagen der Adresse ist ein Fehler aufgetreten No text record found Error with the DNS - Kein Text Eintrag im DNS gefunden + Kein Texteintrag gefunden Unexpected number of values in text record Error with the DNS - Unerwartete Anzahl von Werten im Texteintrag + Unerwartete Anzahl an Einträgen in Text The version of Tox DNS used by this server is not supported Error with the DNS - Die Tox DNS Version dieses Servers wird nicht unterstützt + Die von diesem Server verwendete Version von Tox DNS wird leider nicht unterstützt The DNS lookup does not contain any Tox ID Error with the DNS - Der DNS Eintrag enthält keine Tox ID + Die ToxDNS Nachfrage konnte keine Tox ID finden The DNS lookup does not contain a valid Tox ID Error with the DNS - Der DNS Eintrag enthält keine gültige TOX ID + Die ToxDNS Nachfrage konnte keine gültige Tox ID finden @@ -2071,48 +2076,44 @@ Es wird beim Neustart von qTox installiert. It appears that qTox has to use the old tox1 protocol to access DNS record of your friend's Tox ID. Unfortunately tox1 is not secure, and you are at risk of someone hijacking what is sent between you and ToxDNS service. Should tox1 be used anyway? -If unsure, press “No”, so that request to ToxDNS service will not be made using unsecure protocol. - - - - It appears that qTox has to use the old tox1 protocol. -Unfortunately tox1 is not secure. Should it be used anyway? - Es scheint, dass qTox das veraltete tox1-Protokoll nutzen muss. -Dieses Protokoll ist nicht sicher. -Soll es dennoch genutzt werden? +If unsure, press “No”, so that request to ToxDNS service will not be made using unsecure protocol. + Es scheint, dass qTox ein altes Protokoll verwenden muss, um sich mit deinem Kontakt zu verbinden. +Leider ist die Alternativmethode nicht sicher und es besteht die Gefahr, dass an ToxDNS gesendete Daten abgefangen werden. +Soll das Alternativprotokoll trotzdem verwendet werden? +Falls du dir nicht sicher bist, wähle 'Nein'. ToxURIDialog - + Add a friend Title of the window to add a friend through Tox URI Einen Freund hinzufügen - + Do you want to add %1 as a friend? - Wollen Sie %1 als Freund hinzufügen? + Möchtest du %1 als Kontakt in deine Liste aufnehmen? - + User ID: - Benutzer ID: + ID: - + Friend request message: Freundschaftsanfrage: - + Send Send a friend request - Senden + Freundschaftsanfrage senden - + Cancel Don't send a friend request Abbrechen @@ -2121,167 +2122,134 @@ Soll es dennoch genutzt werden? Widget - Online - Online - - - Away - Abwesend - - - Busy - Beschäftigt - - - - &Quit - &Beenden - - - Change status to: - Ändert den Status in: - - - + Online Button to set your status to 'Online' Online - + Away Button to set your status to 'Away' Abwesend - + Busy Button to set your status to 'Busy' Beschäftigt - Choose a profile - Wählen Sie ein Profil - - - Please choose which identity to use - Wählen Sie die Identität, die benutzt werden soll - - - - Choose a profile picture - Wählen Sie ein Profilbild - - - - - - Error - Fehler - - - - Unable to open this file - Kann diese Datei nicht öffnen - - - - Unable to read this image - Kann dieses Bild nicht einlesen - - - - This image is too big - Dieses Bild ist zu groß - - - + Toxcore failed to start, the application will terminate after you close this message. - Tox startet nicht, die Anwendung wird nach Schließen dieses Fensters beendet. + Entschuldige, es ist ein Fehler aufgetreten und die Anwendung lässt sich nicht starten. - + toxcore failed to start with your proxy settings. qTox cannot run; please modify your settings and restart. popup text - Tox startet nicht mit ihren Proxy-Einstellungen. qTox funktioniert nicht, ändern Sie bitte Ihre Einstellungen und starten qTox neu. + Entschuldige, es ist ein Fehler aufgetreten und die Anwendung kann nicht gestartet werden. +Leider führen deine Proxyeinstellungen zu Problemen. Bitte ändere deine Einstellungen und versuche es erneut. - + Add friend - Freund hinzufügen + Einen Freund hinzufügen - + File transfers Dateiübertragungen - + + Executable file + popup title + Ausführbare Datei + + + + 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 + Du hast qTox aufgefordert eine Datei auszuführen. Bitte beachte, dass ausführbare Dateien ein Sicherheitsrisiko darstellen können. Bist du dir sicher, dass du die Datei ausführen möchtest? + + + Settings Einstellungen - - Couldn't request friendship - Freundschaftsanfrage fehlgeschlagen + + Profile + Profil - + + Couldn't request friendship + Freundschaftsanfrage konnte nicht gesendet werden + + + away contact status Abwesend - + busy contact status Beschäftigt - + offline contact status Offline - + online contact status Online - + %1 is now %2 e.g. "Dubslow is now online" - %1 ist nun %2 + %1 ist jetzt %2 - + Group invite popup title - + Gruppeneinladung - + %1 has invited you to a groupchat. Would you like to join? popup text - + %1 hat dich in eine Gruppe eingeladen! Möchtest du ihr beitreten? - + <Unknown> Placeholder when we don't know someone's name in a group chat <Unbekannt> - + %1 has set the title to %2 %1 hat den Titel auf %2 gesetzt - + + &Quit + Beenden + + + Message failed to send - Senden der Nachricht fehlgeschlagen + Nachricht konnte nicht gesendet werden From c3c370d118086ebd71f06161918bb0610521c886 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 22:56:46 +0200 Subject: [PATCH 34/51] Cherry-pick da084594d9b58a5cbaf2414efecac04700c72ab4 from #1523 Closes #1523 From 7b3baa893222becc2421265065cb29aed3e1f214 Mon Sep 17 00:00:00 2001 From: AxP Date: Sun, 12 Apr 2015 14:23:50 +0200 Subject: [PATCH 35/51] German translation updated. --- translations/de.ts | 2166 ++++++++++++++++++++++---------------------- 1 file changed, 1067 insertions(+), 1099 deletions(-) diff --git a/translations/de.ts b/translations/de.ts index edac3b357..daad748e4 100644 --- a/translations/de.ts +++ b/translations/de.ts @@ -1,6 +1,6 @@ - + AVForm @@ -9,38 +9,40 @@ Audio/Video - + Initializing Camera... - Initialisiert Kamera... + Initialisiere Kamera... AVSettings - - Playback - Wiedergabe + + Audio Settings + Die Frage hier ist immer ob man mit Leerzeichen oder Bindestrich übersetzt. Meiner Meinung sieht das aber nicht gut aus. Toneinstellungen alternativ. + Audioeinstellungen Microphone - Mikrofon + Die englische Übersetzung erscheint mir unpassend. + Aufnahmelautstärke - - Audio Settings - Audio Einstellungen + + Playback + Wiedergabelautstärke Use slider to set volume of your speakers. - + Verwende den Schieber um die Wiedergabelautstärke anzupassen. Use slider to set volume of your microphone. WARNING: slider is not supposed to work yet. - + Verwende den Schieber um die Aufnahmelautstärke deines Mikrofons anzupassen. @@ -55,27 +57,27 @@ WARNING: slider is not supposed to work yet. Rescan audio devices - Erneut nach Audiogeräten suchen + Audiogeräte aktualisieren Filter audio - Audiofilter + Aufnahme filtern Filter sound from your microphone, so that people hearing you would get better sound. - + Die Filterung verbessert deine Sprachqualität. Video Settings - Video Einstellungen + Videoeinstellungen Resolution - Auflösung + Kameraauflösung @@ -85,7 +87,9 @@ The higher values, the better video quality your friends may get. Note though that with better video quality there is needed better internet connection. Sometimes your connection may not be good enough to handle higher video quality, which may lead to problems with video calls. - + Wähle deine Kameraauflösung. +Höhere Werte führen zu einem schärferen Bild, allerdings nimmt die Netzwerkauslastung zu. +Zu hohe Auflösungen können zu Problemen in Videokonferenzen führen. @@ -111,57 +115,68 @@ which may lead to problems with video calls. AddFriendForm - + Add Friends - Freunde hinzufügen + Einen Freund hinzufügen - + Tox ID Tox ID of the person you're sending a friend request to Tox ID - + Message The message you send in friend requests - Nachricht + Freundschaftsanfrage - + Send friend request - Freundschaftsanfrage versenden + Freundschaftsanfrage senden - - Tox me maybe? + + %1 here! Tox me maybe? Default message in friend requests if the field is left blank. Write something appropriate! - Lass uns toxen! + Hallo, +Hier ist %1! Hast du Lust dich mit mir zu unterhalten? + +Viele Grüße +%1 - + + + + Couldn't add friend + Freund konnte nicht hinzugefügt werden + + + Please fill in a valid Tox ID Tox ID of the friend you're sending a friend request to - Geben Sie bitte eine gültige Tox ID ein + Entschuldigung, das hat nicht geklappt. Bitte gib eine korrekte ID an! - + You can't add yourself as a friend! When trying to add your own Tox ID as friend - Sie können sich nicht selbst als Freund hinzufügen! + Entschuldige, aber du kannst dich nicht mit dir selbst anfreunden! - + qTox needs to use the Tox DNS, but can't do it through a proxy. Ignore the proxy and connect to the Internet directly? - qTox muss das Tox DNS nutzen, dies klappt allerdings nicht über einen Proxy. -Soll der Proxy ignoriert und eine direkte Internetverbindung genutzt werden? + qTox verwendet Tox-DNS, um eine Verbindung herzustellen, aber kann das nicht mit einem aktivierten Proxyserver. +Soll der Proxyserver ignoriert werden und eine Direktverbindung hergestellt werden? - + This Tox ID does not exist DNS error - Tox ID existiert nicht + Entschuldigung, aber diese ID existiert scheinbar nicht! @@ -169,22 +184,23 @@ Soll der Proxy ignoriert und eine direkte Internetverbindung genutzt werden? Advanced - Fortgeschritten + Erweitert FULL - very safe, slowest (recommended) - VOLL - sehr sicher, langsam (empfohlen) + Die englischen Bezeichnungen scheinen mir irreführend. Normal sollte der Fall sein der keine Probleme bereitet und empfohlen ist. + Synchron NORMAL - almost as safe as FULL, about 20% faster than FULL - NORMAL - fast so sicher wie VOLL, ca. 20% schneller + Teilweise asynchron OFF - disables all safety, when something goes wrong your history may be lost, fastest (not recommended) - AUS - keinerlei Sicherheit, geht etwas schief, kann die Historie verloren gehen, ist am schnellsten (nicht empfohlen) + Vollständig asynchron (unsicher) @@ -192,42 +208,45 @@ Soll der Proxy ignoriert und eine direkte Internetverbindung genutzt werden? Form + Nicht benötigt. Save settings to the working directory instead of the usual conf dir describes makeToxPortable checkbox - Speichert die Einstellungen im Arbeits- statt im normalen Konfigurationsverzeichnis + Wenn gesetzt werden die Benutzerdaten im Arbeitsverzeichnis gesichert Make Tox portable - Macht Tox portabel + qTox portabel machen <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">IMPORTANT NOTE</span></p><p><span style=" color:#ff0000;">Unless you </span><span style=" font-weight:600; color:#ff0000;">really</span><span style=" color:#ff0000;"> know what you are doing, please do </span><span style=" font-weight:600; color:#ff0000;">not</span><span style=" color:#ff0000;"> change anything here. Changes made here may lead to problems with qTox, and even to loss of your data, e.g. history.</span></p></body></html> - <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">WICHTIGE NOTIZ</span></p><p><span style=" color:#ff0000;">Wenn Sie nicht </span><span style=" font-weight:600; color:#ff0000;">wirklich</span><span style=" color:#ff0000;"> wissen, was Sie tun, ändern Sie hier bitte </span><span style=" font-weight:600; color:#ff0000;">nichts</span><span style=" color:#ff0000;">. Hier getätigte Änderungen können zu Problemen mit qTox führen, evtl. sogar zum Datenverlust, z.B. der Historie.</span></p></body></html> + Der Html Code ist recht übertrieben und enthält Fehler. + <html> +<body style=" font-weight:400; color:#500;"> +<p>Wichtiger Hinweis:</p> +<p>Bitte beachte, dass diese Einstellungen nur geändert werden sollten, wenn du weißt was du tust! Ansonsten kann es zu Beschädigungen der Gesprächsverläufe kommen!</p> +</body> +</html> Reset to default settings - Grundeinstellungen wiederherstellen + Einstellungen zurücksetzen Chat history - - - - History - Historie + Gesprächsverlauf Einstellungen <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;">Synchrones Schreiben in die DB</span></a></p></body></html> + Datenbankverwendung @@ -235,160 +254,216 @@ Soll der Proxy ignoriert und eine direkte Internetverbindung genutzt werden? Form - + Ausgelassen + - - Your name - Ihr Name + + qTox + Ausgelassen + - - Your status - Ihr Status + + Someone + Ausgelassen + - - Add friends - Freunde hinzufügen + + Someone else + Ausgelassen + - - Create a group chat - Gruppenchat anlegen + + Groupbot + Ausgelassen + - - View completed file transfers - Vollendete Dateiübertragungen anzeigen + + That guy who I don't remember adding + Ausgelassen + - - Change your settings - Einstellungen ändern - - - - AndroidGUI - - - Online - Button to set your status to 'Online' - Online + + NASA manager + Ausgelassen + - - Away - Button to set your status to 'Away' - Abwesend + + Lorem + Ausgelassen + - - Busy - Button to set your status to 'Busy' - Beschäftigt + + Ipsum + Ausgelassen + + + + + Dolor + Ausgelassen + ChatForm - Load History... - Historie laden... + + Load chat history... + Gesprächsverlauf laden... - + Send a file Datei versenden - - + + File not read - Datei nicht gelesen + Datei nicht gesendet - - + + qTox wasn't able to open %1 - qTox konnte %1 nicht öffnen + Entschuldigung, %1 konnte nicht geöffnet werden. - - + + Bad Idea - Schlechte Idee + Datei nicht gesendet - - + + You're trying to send a special (sequential) file, that's not going to work! - Sie versuchen eine spezielle (sequentielle) Datei zu senden, das funktioniert nicht! + Entschuldigung, es ist leider nicht möglich diese Art Datei zu senden! - %1 is calling - %1 ruft an + + Accept video call + Videoanruf annehmen - - Load chat history... - + + Accept audio call + Anruf annehmen - + %1 calling - + %1 ruft an - + + + End video call + Videoanruf beenden + + + + + End audio call + Anruf beenden + + + + + Mute microphone + Mikrofon deaktivieren + + + + + Mute call + Ton deaktivieren + + + %1 stopped calling - %1 hat den Anruf beendet + %1 hat aufgelegt - + + Cancel video call + Videoanruf abbrechen + + + + Cancel audio call + Anruf abbrechen + + + Calling to %1 Rufe %1 an - + Call rejected - Anruf abgewiesen + Anruf abgelegt - + + Start audio call + Anruf starten + + + + Start video call + Videoanruf starten + + + + Unmute microphone + Mikrofon aktivieren + + + + Unmute call + Ton aktivieren + + + Failed to send file "%1" - Senden der Datei "%1" fehlgeschlagen + Entschuldigung, %1 konnte nicht gesendet werden - + Call with %1 ended. %2 - Anruf zu %1 beendet. %2 + Anruf mit %1 beendet. %2 - + Call duration: Anrufdauer: - - is typing... - tippt gerade... - ChatLog Copy - + Kopieren Select all - + Alles auswählen - + pending - + Ausstehend @@ -396,188 +471,116 @@ Soll der Proxy ignoriert und eine direkte Internetverbindung genutzt werden? Type your message here... - Nachricht hier eingeben... + Hier eine Nachricht eingeben... Core - + Toxing on qTox - Toxen mit qTox + Tox ist Toll! - + qTox User - qTox Benutzer + Mein Name - + Friend is already added - Freund wurde schon hinzugefügt + Dieser Freund wurde bereits hinzugefügt - + /me offers friendship. - + /me macht eine Freundschaftsanfrage. - + /me offers friendship, "%1" - + /me macht eine Freundschaftsanfrage, "%1" - + Encryption error - Verschlüsselungsfehler + Verschlüsselungsproblem - + The .tox file is encrypted, but encryption was not checked, continuing regardless. - Die .tox Datei ist verschlüsselt, aber die Verschlüsselung wurde nicht geprüft, Vorgang wird trotzdem fortgesetzt. - - - - Please enter the password for the %1 profile. - used in load() when no pw is already set - + Die Datendatei ist verschlüsselt, aber eine Verschlüsselung wurde nicht überprüft! - + Please enter the password for the %1 profile. + used in load() when no pw is already set + Hallo %1, +bitte gib dein Profil-Passwort ein. + + + + The previous password is incorrect; please try again: used on retries in load() - + Entschuldigung, das hat nicht geklappt. Versuch es erneut: - + The profile password failed. Please try another? used only when pw set before load() doesn't work - + Entschuldigung, das Passwort passt nicht. Versuch doch ein anderes! - + + Change profile + Profil wechseln + + + Encrypted chat history - + Verschlüsselter Gesprächsverlauf - + No encrypted chat history file found, or it was corrupted. History will be disabled! - + Entschuldige, die Verlaufsdatei wurde nicht gefunden oder ist beschädigt. +Die Verlaufsfunktion wird erst einmal ausgeschaltet! - + Please enter the password for the chat history for the %1 profile. used in load() when no hist pw set - + %1, bitte gib dein Gesprächsverlaufpasswort ein. - + Disabling chat history now will leave the encrypted history intact (but not usable); if you later remember the password, you may re-enable encryption from the Privacy tab with the correct password to use the history. part of history password dialog - + Wenn du die Verlaufsfunktion jetzt deaktivierst, wird dir die verschlüsselte Verlaufsdatei erhalten bleiben. Sollte dir später das Passwort wieder einfallen, kannst du deinen alten Verlauf weiterverwenden. - + The chat history password failed. Please try another? used only when pw set before load() doesn't work - + Entschuldigung, das Passwort für deinen Verlauf hat nicht gepasst. Versuch es erneut! - + Disable chat history - + Verlaufsfunktion deaktivieren - - Encryption is enabled, but there is no password! Encryption will be disabled. - - - - Tox datafile decryption password - Entschlüsselungspasswort für Tox Datendatei - - - Password error - Passwortfehler - - - Failed to setup password. -Empty password. - Setzen des Passwortes fehlgeschlagen. -Leeres Passwort. - - - Try Again - Nochmal versuchen - - - - Change profile - Profil ändern - - - Reinit current profile - Aktuelles Profil erneut starten - - - Wrong password has been entered - Es wurde ein falsches Passwort eingegeben - - - History Log decryption password - Passwort zur Entschlüsselung der Historie - - - Encrypted log - Verschlüsselte Logdatei - - - Your history is encrypted with different password. -Do you want to try another password? - Ihre Historie wurde mit einem anderen Passwort verschlüsselt. -Wollen Sie ein weiteres probieren? - - - Due to incorret password history will be disabled. - Falsches Passwort, Historie wird deaktiviert. - - - History - Historie - - - + NO Password - KEIN Passwort + Passwort fehlt - Will be saved without encryption! - Wird ohne Verschlüsselung gespeichert! - - - - FileTransferInstance - - Save a file - Title of the file saving dialog - Datei speichern - - - Location not writable - Title of permissions popup - Ort schreibgeschützt - - - You do not have permission to write that location. Choose another, or cancel the save dialog. - text of permissions popup - Sie haben keine Erlaubnis, die Datei in diesen Ort zu speichern. Wählen Sie einen anderen Ort oder beenden Sie den Dialog. - - - ETA - ETA + + Local file encryption is enabled, but there is no password! It will be disabled. + Die Verschlüsselung der lokalen Dateien ist aktiviert, aber es ist kein Passwort vorhanden. Die Verschlüsselung wird deswegen abgeschaltet. @@ -585,87 +588,93 @@ Wollen Sie ein weiteres probieren? Form - + Ausgelassen + 10Mb - + Ausgelassen + 0kb/s - + Ausgelassen + ETA:10:10 - + Ausgelassen + Filename - + Ausgelassen + [preview] - + Ausgelassen + - + Waiting to send... file transfer widget - + Dateitransfer läuft... - + Accept to receive this file file transfer widget - + Akzeptiere, um die Datei zu empfangen - + Location not writable Title of permissions popup - Ort schreibgeschützt + Ordner nicht beschreibbar - + You do not have permission to write that location. Choose another, or cancel the save dialog. text of permissions popup - Sie haben keine Erlaubnis, die Datei in diesen Ort zu speichern. Wählen Sie einen anderen Ort oder beenden Sie den Dialog. + Du besitzt nicht die Rechte um hier eine Datei zu speichern. Bitte wähle einen anderen Ordner oder breche die Aktion ab. - + paused file transfer widget - + Pausiert - + Save a file Title of the file saving dialog - Datei speichern + Datei speichern FilesForm - + Transfered Files "Headline" of the window Übertragene Dateien - + Downloads - Heruntergeladen + Heruntergeladene Dateien - + Uploads - Hochgeladen + Hochgeladene Dateien @@ -679,12 +688,12 @@ Wollen Sie ein weiteres probieren? Someone wants to make friends with you - Jemand möchte Ihr Freund werden + Jemand lädt dich in seine Kontaktliste ein User ID: - Benutzer ID: + ID: @@ -707,101 +716,101 @@ Wollen Sie ein weiteres probieren? FriendWidget - + Invite to group Menu to invite a friend to a groupchat - In Gruppe einladen + Gruppeneinladung - + Copy friend ID Menu to copy the Tox ID of that friend - Tox ID kopieren - - - - Set alias... - Alias setzen... + ID kopieren + Set alias... + Namen setzen... + + + Auto accept files from this friend context menu entry Dateien von diesem Freund automatisch annehmen - - Choose an auto accept directory - popup title - Wähle ein Verzeichnis für die automatische Dateiannahme - - - - User alias - Benutzeralias - - - - You can also set this by clicking the chat form name. -Alias: - Sie können diesen auch durch Klick auf den Namen des Chatfensters festlegen. -Alias: - - - + Remove friend Menu to remove the friend from our friendlist - Freund entfernen + Freund löschen + + + + Choose an auto accept directory + popup title + Speicherort angeben + + + + User alias + Nutzername + + + + You can also set this by clicking the chat form name. +Alias: + Bitte trage hier einen neuen Namen ein. +Das lässt sich auch durch einen Klick auf den Namen im Chat erreichen. GUI - + Enter your password - + Passworteingabe - + Decrypt - + Entschlüsseln - + You must enter a non-empty password: - + Du musst ein nicht-leeres Passwort angeben: GeneralForm - + General - Allgemein + Allgemeines - - + + None - Kein + Nichts - + Choose an auto accept directory popup title - Wählen Sie ein Verzeichnis + Datei-Speicherort angeben - + Call active popup title - Anwahl aktiviert + Anruf aktiv - + You can't disconnect while a call is active! popup text - Abbruch während der Anwahl nicht möglich! + Du kannst dich nicht abmelden solange ein Anruf aktiv ist! @@ -815,32 +824,7 @@ Alias: The translation may not load until qTox restarts. - Änderung wird erst nach Neustart von qTox aktiv. - - - - Show system tray icon - In der Systemleiste anzeigen - - - - Start in tray - In die Systemleiste starten - - - - Close to tray - In die Systemleiste schließen - - - - Minimize to tray - In die Systemleiste minimieren - - - - Light icon - Helles Icon + qTox muss neugestartet werden, um die Änderungen zu übernehmen. @@ -852,67 +836,113 @@ Alias: System tray Systemleiste + + + Show system tray icon + Icon in Systemleiste + Enable light tray icon. toolTip for light icon setting - + Helles Icon aktivieren. + + + + Light icon + Helles Icon qTox will start minimized in tray. toolTip for Start in tray setting - + Wenn aktiv, qTox startet minimiert. + + + + Start in tray + Im Hintergrund starten After pressing close (X) qTox will minimize to tray, instead of closing itself. toolTip for close to tray setting - + Wenn aktiv, qTox wird nicht sofort beendet, sondern in die Systemleiste minimiert. + + + + Close to tray + In Systemleiste schließen After pressing minimize (_) qTox will minimize itself to tray, instead of system taskbar. toolTip for minimize to tray setting - + Wenn aktiv, qTox wird in die Systemleiste minimiert. + + + + Minimize to tray + In Systemleiste minimieren <html><head/><body><p>Start qTox on operating system startup (current profile).</p></body></html> - + Wenn aktiv, qTox wird bei Systemstart geladen. Autostart - + Mit Betriebssystem starten Check for updates on startup - Beim Starten auf Updates überprüfen + Beim Start nach Updates suchen Set where files will be saved. - + Datei-Speicherort angeben. Save to: - Speichern in: + Speicherort: + + + + You can set this on a per-friend basis by right clicking them. + autoaccept cb tooltip + Dies lässt sich für jeden Kontakt einzeln einstellen. (Rechtsklickmenü) + + + + Autoaccept files + Dateien automatisch annehmen + + + + Set to 0 to disable + '0' deaktiviert die Funktion + + + + minutes + Minuten Your status is changed to Away after set period of inactivity. - + Nach einer Weile wird dein Status auf 'Abwesend' gesetzt. Auto away after (0 to disable): - Automatisch abwesend nach (0 zum Deaktivieren): + Automatisch abwesend nach (Aus = 0): @@ -923,236 +953,196 @@ instead of system taskbar. Always notify about new messages in groupchats. toolTip for Group chat always notify - + Immer auf neue Nachrichten in Gruppenchats hinweisen. Group chats always notify - Über Gruppenchats immer informieren + Gruppenchat Hinweise Show contacts' status changes - Zeigt Statusänderungen der Kontakte + Hinweis bei Statusänderungen + + + + On new message: + Bei neuen Nachrichten: Show qTox's window when you receive new message. tooltip for Show window setting - + Öffne qTox bei neuen Nachrichten. + + + + Show window + Öffne Chat Focus qTox when you receive message. toolTip for Focus window setting - - - - - Messages you are trying to send to your friends when they are not online -will be sent to them when they will appear online to you. - toolTip for Faux offline messaging setting - - - - - Faux offline messaging - Imitiert Offline Benachrichtigung - - - Compact contact list (restart required) - Kompakte Darstellung der Kontaktliste (Neustart benötigt) - - - Provided in minutes - Angabe in Minuten - - - Auto away after (0 to disable) - Automatisch abwesend nach (0 deaktiviert) - - - - Set to 0 to disable - Zum Deaktivieren auf 0 setzen - - - - You can set this on a per-friend basis by right clicking them. - autoaccept cb tooltip - Sie können dies durch Rechtsklick auf den jeweiligen Freund festlegen. - - - - Use emoticons - Emoticons benutzen - - - Smiley Pack - Text on smiley pack label - Emoticon Paket - - - Style - Stil - - - Theme color - Farbe - - - Emoticon size - Emoticon Größe - - - - px - Pixel - - - Timestamp format - Zeitformat - - - - Disabling this allows, e.g., toxing over Tor. It adds load to the Tox network however, so uncheck only when necessary. - force tcp checkbox tooltip - Wenn deaktiviert kann z.B. über Tor getoxt werden. Dies belastet das Tox Netzwerk zusätzlich und sollte nur deaktiviert werden wenn notwendig. - - - - Enable UDP (recommended) - Text on checkbox to disable UDP - UDP aktivieren (empfohlen) - - - - Proxy type: - Proxy Typ: - - - - Address: - Text on proxy addr label - Adresse: - - - - SOCKS5 - SOCKS5 - - - - HTTP - HTTP - - - - Reconnect - reconnect button - Erneut verbinden - - - - minutes - Minuten - - - - Autoaccept files - Dateien automatisch annehmen - - - PushButton - Schaltfläche - - - - On new message: - Bei neuer Nachricht: - - - - Show window - Zeige Fenster + Auf Fenster fokussieren, wenn neue Nachrichten eingehen. Focus window - Bringe Fenster in den Vordergrund + Fokussiere das Fenster - - Your contact list will be shown in compact mode. - toolTip for compact layout setting - + + Play a sound when you recieve message. + toolTip for Notify sound setting + Bei neuen Nachrichten einen Ton abspielen. + + + + Play sound + Spiele einen Ton ab + + + + Messages you are trying to send to your friends when they are not online +will be sent to them when they appear online to you. + toolTip for Faux offline messaging setting + Offline-Nachrichten werden übertragen, sobald der entsprechende Kontakt verfügbar wird, während du online bist. + Faux offline messaging + Pseudo-Offline Nachrichten + + + + Your contact list will be shown in compact mode. + toolTip for compact layout setting + Die Kontaktliste wird kompakter dargestellt. + + + Compact contact list Kompakte Kontaktliste - - Theme - Benutzeroberfläche + + If checked, groupchats will be placed at the top of the friends list, otherwise, they'll be placed below online friends. + toolTip for groupchat positioning + Stelle Gruppenchats über die normalen Kontakte. - + + Place groupchats at top of friend list + Gruppenchats oben + + + + Theme + Aussehen + + + + Use emoticons + Emoticons verwenden + + + Smiley Pack: Text on smiley pack label - Smiley Paket: + Smiley Art: - + Emoticon size: - Emoticon Größe: + Smileygröße: - + + px + Pixel + + + Style: - Stil: + Grundstil: - + Theme color: - Fensterfarbe: + Grundfarbe: - + Timestamp format: Zeitformat: - + + Date format: + Datumsformat: + + + Connection Settings Verbindungseinstellungen - + + Disabling this allows, e.g., toxing over Tor. It adds load to the Tox network however, so uncheck only when necessary. + force tcp checkbox tooltip + Wenn deaktiviert, lässt sich qTox mit Tor verwenden. Die Deaktivierung belastet allerdings das Tox-Netzwerk. + + + + Enable UDP (recommended) + Text on checkbox to disable UDP + UDP aktivieren (Empfohlen) + + + Enable IPv6 (recommended) Text on a checkbox to enable IPv6 - IPv6 aktivieren (empfohlen) + IPv6 aktivieren (Empfohlen) - Proxy type - Proxy Typ + + Proxy type: + Proxy-Typ: - - None - Keinen - - - Address + + Address: Text on proxy addr label - Adresse + Addresse: - + Port Text on proxy port label - Port + Port: + + + + None + Kein Proxy + + + + SOCKS5 + + + + + HTTP + + + + + Reconnect + reconnect button + Erneut verbinden @@ -1160,7 +1150,7 @@ will be sent to them when they will appear online to you. Send message - Nachricht senden + Nachricht versenden @@ -1170,382 +1160,270 @@ will be sent to them when they will appear online to you. Send file(s) - Datei(en) senden + Datei senden - Audio call: RED means you're on a call - Sprachanruf: ROT bedeutet verbunden + Start an audio call + Anruf starten - Video call: RED means you're on a call - Videoanruf: ROT bedeutet verbunden - - - - Toggle speakers volume: RED is OFF - Schaltet den Lautsprecher ein/aus: ROT ist AUS - - - - Toggle microphone: RED is OFF - Schaltet das Mikrofon ein/aus: ROT ist AUS + Start a video call + Videoanruf starten - + Save chat log - Chatverlauf speichern + Gesprächsverlauf speichern Clear displayed messages - Angezeigte Nachrichten ausblenden + Angezeigte Nachrichten entfernen - + Not sent - + Nicht gesendet - + Cleared - Ausgeblendet + Gesprächsverlauf entfernt GroupChatForm - + %1 users in chat Number of users in chat - %1 Teilnehmer im Chat + %1 Kontakte im Chat - + %1 users in chat - %1 Teilnehmer im Chat + %1 Kontakt im Chat + + + + + Start audio call + Anruf starten + + + + + Mute microphone + Mikrofon deaktivieren + + + + Unmute microphone + Mikrofon aktivieren + + + + + Mute call + Ton deaktivieren + + + + Unmute call + Ton aktivieren + + + + End audio call + Anruf beenden GroupWidget - - - - %1 users in chat - %1 Teilnehmer im Chat - - + + %1 users in chat + %1 Kontakte im Chat + + + + 0 users in chat - kein Teilnehmer im Chat + Keine Kontakte im Chat - + Set title... - Titel festlegen... + Titel wählen... - + Quit group Menu to quit a groupchat Gruppe verlassen - + Group title - Gruppentitel + Gruppenname - + You can also set this by clicking the chat form name. Title: - Sie können diesen auch durch Klick auf den Namen des Chatfensters festlegen. -Titel: - - - - IdentityForm - - - Identity - Identität - - - - Call active - popup title - Anruf aktiv - - - - You can't switch profiles while a call is active! - popup text - Das Profil kann während eines Anrufes nicht gewechselt werden! - - - - Rename "%1" - renaming a profile - "%1" umbenennen - - - - Profile already exists - rename confirm title - Profil existiert bereits - - - - A profile named "%1" already exists. Do you want to erase it? - rename confirm text - Ein Profil mit dem Namen "%1" existiert bereits. Wollen Sie es löschen? - - - - Export profile - save dialog title - Profil exportieren - - - - Tox save file (*.tox) - save dialog filter - Toxdatei speichern (*.tox) - - - - Failed to remove file - Entfernen der Datei fehlgeschlagen - - - - The file you chose to overwrite could not be removed first. - Die gewählte Datei kann nicht überschrieben werden. - - - - Failed to copy file - Kopieren der Datei fehlgeschlagen - - - - The file you chose could not be written to. - Die gewählte Datei kann nicht überschrieben werden. - - - - Profile currently loaded - current profile deletion warning title - Profil ist zurzeit geladen - - - - This profile is currently in use. Please load a different profile before deleting this one. - current profile deletion warning text - Dieses Profil ist aktuell in Gebrauch. Bitte laden Sie vor dem Löschen ein anderes Profil. - - - - Deletion imminent! - deletion confirmation title - Löschen steht bevor! - - - - Are you sure you want to delete this profile? - deletion confirmation text - - - - Are you sure you want to delete this profile? -Associated friend information and chat logs will be deleted as well. - deletion confirmation text - Wollen Sie dieses Profil wirklich löschen? -Dazugehörige Informationen und Chatprotokolle werden ebenfalls gelöscht. - - - - Import profile - import dialog title - Profil importieren - - - - Tox save file (*.tox) - import dialog filter - Toxdatei speichern (*.tox) - - - - Ignoring non-Tox file - popup title - Keine Toxdatei, wird ignoriert - - - - Warning: you've chosen a file that is not a Tox save file; ignoring. - popup text - Warnung: Sie haben eine Datei gewählt, die keine Toxdatei ist, wird ignoriert. - - - - Profile already exists - import confirm title - Profil existiert bereits - - - - A profile named "%1" already exists. Do you want to erase it? - import confirm text - Ein Profil mit dem Namen "%1" existiert bereits. Wollen Sie es löschen? + Lässt sich auch durch einen Klick auf den Name im Chat ändern. +Name: IdentitySettings - + Public Information Öffentliche Informationen - + Name - Benutzername + Dein Name - + Status - Status + Dein Status - + Tox ID - Tox ID + ID Informationen - + + This bunch of characters tells other Tox clients how to contact you. Share it with your friends to communicate. Tox ID tooltip - + Dies ist deine persönliche Addresse. Damit können dich andere qTox-Nutzer erreichen. +Teile sie einfach deinen Bekannten mit! - + Your Tox ID (click to copy) - Ihre Tox ID (klicken zum Kopieren) + Deine Tox ID (Klicken zum kopieren) - + + QRCODE + Ausgelassen + + + + + This QR code contains your Tox ID. You may share this with your friends as well. + Ein QR-Code, der deine Tox ID enthält. Dieser lässt sich anstatt der ID verwenden! + + + + Save image + Bild speichern + + + + Copy image + Bild kopieren + + + Profiles - Profile + Profil Informationen - + Available profiles: Verfügbare Profile: - + Currently selected profile. toolTip for currently set profile - + Zurzeit verwendetes Profile. - + Load selected profile and switch to it. tooltip for loading profile button - + Ausgewähltes Profil laden und verwenden. - Switching profiles is disabled during calls - tooltip - Profilwechsel ist während eines Anrufes deaktiviert - - - + Load load profile button - Laden + Profil laden - + + Rename selected profile. + tooltip for renaming profile button + Ausgewähltes Profil umbenennen. + + + Rename rename profile button Umbenennen - - Rename selected profile. - tooltip for renaming profile button - + + Allows you to export your Tox profile to a file. +Profile does not contain your history. + tooltip for profile exporting button + Speichert das ausgewählte Profil in eine Datei. Beachte, dass diese Datei deinen Gesprächsverlauf <i>nicht</i> enthält! - + Export export profile button Exportieren - - Allows you to export your Tox profile to a file. -Profile does not contain your history. - tooltip for profile exporting button - - - - + Delete selected profile. delete profile button tooltip - + Löscht das oben ausgewählte Profil. - + Delete delete profile button Löschen - + Import Tox profile from a .tox file. tooltip for importing profile button - + Importiert ein Profil in Form einer <i>*.tox</i> Datei. - - Create new Tox ID and switch to it. - tooltip for creating new Tox ID button - - - - - New Tox ID - new profile button - Neue Tox ID - - - This is useful to remain safe on public computers - delete profile button tooltip - Dies ist nützlich, um auf öffentlichen Computern sicher zu sein - - - + Import a profile import profile button - Importieren - - - - InputPasswordDialog - - Password Dialog - Passwort + Profil importieren - Input password: - Passwort eingeben: + + Create new Tox ID and switch to it. + tooltip for creating new Tox ID button + Erstellt ein neues Profil und wechselt zu diesem. + + + + New Tox ID + new profile button + Neues Profil @@ -1553,48 +1431,48 @@ Profile does not contain your history. Load History Dialog - Historie laden + Gesprächsverlauf Load history from: - Lade die Historie vom: + Den Verlauf von einem bestimmten Datum bis Heute anzeigen: MainWindow - + Your name - Ihr Name + Dein Name - + Your status - Ihr Status + Dein Status - + Add friends - Freunde hinzufügen + Einen Freund hinzufügen - + Create a group chat - Gruppenchat anlegen + Eine neue Gruppe eröffnen - + View completed file transfers - Vollendete Dateiübertragungen anzeigen + Dateiverläufe anzeigen - + Change your settings Einstellungen ändern - + Close Schließen @@ -1604,16 +1482,16 @@ Profile does not contain your history. Tox video - Tox Video + qTox Videokonferenz Nexus - + Images (%1) filetype filter - + Bilder (%1) @@ -1626,103 +1504,118 @@ Profile does not contain your history. Please set your new chat history password. - Bitte Passwort zum Verschlüsseln des Chatverlaufs setzen. + Bitte wähle ein neues Passwort für die Verschlüsselung deiner Gesprächsverläufe. It appears you have an unused encrypted chat history; if the password matches, it will be added to your current history. - Es scheint als gäbe es einen unverschlüsselten Chatverlauf. Wenn die Passwörter übereinstimmen wird dieser zum aktuellen Chatverlauf hinzugefügt. + Es scheint, dass bereits eine verschlüsselte Verlaufsdatei vorhanden ist. Sollte das angegebene Passwort passen, wird diese weiterverwendet. Use data file password pushbutton text - Nutze das Tox-Datendatei Passwort + Das Datenpasswort verwenden Successfully decrypted old chat history popup title - Alter Chatverlauf erfolgreich entschlüsselt + Der alte Verlauf wurde erfolgreich entschlüsselt You have succesfully decrypted the old chat history, and it has been added to your current history and re-encrypted. popup text - Der alte Chatverlauf wurde erfolgreich entschlüsselt, zum aktuellen Chatverlauf hinzugefügt und wieder verschlüsselt. + Die alte Verlaufsdatei wurde erfolgreich entschlüsselt und wurde in deine aktuellen Verläufe integriert. Old encrypted chat history popup title - Alter verschlüsselter Chatverlauf + Ehemalige Gesprächsverläufe There is currently an unused encrypted chat history, but the password you just entered doesn't match. -If you don't care about the old history, you may click Ok to delete it and use the password you just entered. -Otherwise, hit cancel to try again. +If you don't care about the old history, you may delete it and use the password you just entered. +Otherwise, hit Cancel to try again. This happens when enabling encryption after previously "Disabling History" - + Es ist eine ehemalige Verlaufsdatei vorhanden, allerdings passt das Passwort nicht, dass du angegeben hast. + +Wenn es dich nicht stört, kann sie gelöscht und das neue Passwort verwendet werden. +Falls doch, drücke auf Abbrechen und versuche es erneut. + + + + + + + Delete + Löschen + + + + + + + + Cancel + Abbrechen Are you absolutely sure you want to lose the unused encrypted chat history? secondary popup - + Bestätige, dass du die alten Verläufe löschen möchtest. + + + + + Old encrypted chat history + title + Ehemalige Gesprächsverläufe - - Old encrypted chat history - title - Alter verschlüsselter Chatverlauf - - - Would you like to decrypt your chat history? Otherwise it will be deleted. - Möchten Sie den Chatverlauf entschlüsseln? -Ansonsten wird dieser gelöscht. + Möchtest du deinen Gesprächsverlauf entschlüsseln oder lieber löschen? - + + + Decrypt + Entschlüsseln + + + Are you sure you want to lose your entire chat history? - Sind Sie sicher, dass der gesamte Chatverlauf gelöscht werden soll? + Bestätige, dass du deine Gesprächsverläufe löschen möchtest. - + Please set your new data file password. - Bitte Passwort zum Verschlüsseln der Datendatei setzen. + Bitte wähle ein neues Passwort für deine Daten. - + Use chat history password pushbutton text - Nutze das Chatverlauf-Passwort + Gesprächsverlauf-Passwort wiederverwenden - + Decrypt your data file title - Datendatei entschlüsseln + Datendatei entschlüsseln - + Would you like to decrypt your data file? - Möchten Sie die Datendatei entschlüsseln? - - - Encrypted log - Verschlüsselte Logdatei - - - You already have history log file encrypted with different password -Do you want to delete old history file? - Es gibt schon eine Historie Logdatei mit einem anderen Passwort. -Soll die alte Historiedatei gelöscht werden? + Bestätige, dass du deine Datendatei entschlüsseln möchtest. @@ -1731,44 +1624,55 @@ Soll die alte Historiedatei gelöscht werden? Your friends will be able to see when you are typing. tooltip for typing notifications setting - + Wenn aktiviviert, können deine Kontakte sehen, dass du tippst. Send Typing Notifications - Tippen anzeigen + Eingabehinweis senden Chat history keeping is still in development. Save format changes are possible, which may result in data loss. toolTip for Keep History setting - + Wenn aktiviert, wird der Gesprächsverlauf dauerhaft gesichert. Keep chat history (mostly stable) - Chatverlauf speichern (größtenteils stabil) + Gesprächsverläufe dauerhaft sichern Local file encryption - Lokale Dateien verschlüsseln + Verschlüsselung All Tox communications over the internet are encrypted, and this cannot be disabled. However, you may optionally password protect your local Tox files. - Die gesamte Tox-Kommunikation über das Internet ist verschlüsselt und kann auch nicht deaktiviert werden. Es ist optional auch möglich, die lokal gespeicherten Tox-Daten mit einem Passwort zu schützen. + Jegliche Kommunikation über qTox ist vollständig verschlüsselt. Diese Funktion lässt sich <i>nicht</i> deaktiviern. Darüber hinaus kannst du deine lokalen Dateien verschlüsseln. Encrypt Tox data file - Tox Datendatei verschlüsseln + Datendateien verschlüsseln + + + + + Change password + Passwort wechseln Encrypt chat history - Chatverlauf verschlüsseln + Gesprächsverläufe verschlüsseln + + + + Nospam + Störende Anfragen blockieren @@ -1777,199 +1681,300 @@ It is there to help you change your Tox ID when you feel like you are getting to 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 - - - - - - Change password - Passwort ändern - - - Please set your new chat history password. - Bitte Passwort zum Verschlüsseln des Chatverlaufs setzen. - - - It appears you have an unused encrypted chat history; if the password matches, it will be added to your current history. - Es scheint als gäbe es einen unverschlüsselten Chatverlauf. Wenn die Passwörter übereinstimmen wird dieser zum aktuellen Chatverlauf hinzugefügt. - - - Use data file password - Nutze das Tox-Datendatei Passwort - - - Successfully decrypted old chat history - Alter Chatverlauf erfolgreich entschlüsselt - - - You have succesfully decrypted the old chat history, and it has been added to your current history and re-encrypted. - Der alte Chatverlauf wurde erfolgreich entschlüsselt, zum aktuellen Chatverlauf hinzugefügt und wieder verschlüsselt. - - - Old encrypted chat history - Alter verschlüsselter Chatverlauf - - - There is currently an unused encrypted chat history, but the password you just entered doesn't match. -Would you like to try again? -Canceling will delete the old history and set the password to what you just entered. - Es gibt aktuell einen ungenutzten verschlüsselten Chatverlauf, aber das eingegebene Passwort stimmt nicht überein. -Möchten Sie ein anderes probieren? -Wenn Sie abbrechen wird der alte Chatverlauf gelöscht und das soeben eingegebene Passwort verwendet. - - - This happens when enabling encryption after previously \"Disabling History\" - Dies passiert, wenn die Verschlüsselung nach einem vorherigen Deaktivieren des Chatverlaufs wieder aktiviert wird. - - - Would you like to decrypt your chat history? -Otherwise it will be deleted. - Möchten Sie den Chatverlauf entschlüsseln? -Ansonsten wird dieser gelöscht. - - - Are you sure you want to lose your entire chat history? - Sind Sie sicher, dass der gesamte Chatverlauf gelöscht werden soll? - - - Please set your new data file password. - Bitte Passwort zum Verschlüsseln der Datendatei setzen. - - - Use chat history password - Nutze das Chatverlauf-Passwort - - - Decrypt your data file - Datendatei entschlüsseln - - - Would you like to decrypt your data file? - Möchten Sie die Datendatei entschlüsseln? - - - The passwords don't match. - Die Passwörter stimmen nicht überein. - - - - Nospam - Spam-Schutz - - - HHHHHHHH - HHHHHHHH + Dies ist ein Teil deiner ID. +Diese ID soll dabei helfen, deine Tox ID zu ändern, falls dich zu viele ungewollte Anfragen erreichen. +Deine bereits vorhandenen Kontakte können dich auch weiterhin erreichen, +nur neue Kontakte benötigen deine neue ID. Generate random nospam - Zufälligen Spam-Schutz erzeugen + ID Generieren + + + + ProfileForm + + + User Profile + Nutzerprofil + + + + Choose a profile picture + Wähle ein Profilbild + + + + + + Error + Fehler beim Öffnen + + + + Unable to open this file + Entschuldige, die ausgewählte Datei konnte nicht geöffnet werden + + + + Unable to read this image + Entschuldige, das ausgewählte Bild konnte nicht gelesen werden + + + + This image is too big + Entschuldige, dieses Bild ist leider etwas zu groß + + + + Call active + popup title + Anruf aktiv + + + + You can't switch profiles while a call is active! + popup text + Entschuldige, aber du kannst dein Profil nicht wechseln, solange ein Anfruf aktiv ist. + + + + Rename "%1" + renaming a profile + Profil '%1' umbenennen + + + + Profile already exists + rename confirm title + Profil bereits vorhanden + + + + A profile named "%1" already exists. Do you want to erase it? + rename confirm text + Entschuldige, aber ein Profil namens '%1' existiert bereits. Möchtest du es überschreiben? + + + + Export profile + save dialog title + Profil exportieren + + + + Tox save file (*.tox) + save dialog filter + Tox Datei (*.tox) + + + + + Location not writable + Title of permissions popup + Verzeichnis nicht beschreibbar + + + + + You do not have permission to write that location. Choose another, or cancel the save dialog. + text of permissions popup + Entschuldige, du scheinst nicht die nötigen Rechte zu haben, um hier eine Datei zu speichern. Wähle doch ein anderes Verzeichnis. + + + + + Failed to copy file + Kopieren fehlgeschlagen + + + + + The file you chose could not be written to. + Entschuldige, aber die gewählte Datei konnte leider nicht beschrieben werden. + + + + Profile currently loaded + current profile deletion warning title + Profil zurzeit in Verwendung + + + + This profile is currently in use. Please load a different profile before deleting this one. + current profile deletion warning text + Dieses Profil wird zurzeit verwendet. Bevor du dieses Profil löschst, solltest du ein anderes laden. + + + + Deletion imminent! + deletion confirmation title + Profil wird gelöscht + + + + Are you sure you want to delete this profile? + deletion confirmation text + Bestätige, dass du das gewählte Profil löschen möchtest. + + + + Import profile + import dialog title + Profil importieren + + + + Tox save file (*.tox) + import dialog filter + Tox Datei (*.tox) + + + + Ignoring non-Tox file + popup title + Nicht-Tox Datei ignoriert + + + + Warning: you've chosen a file that is not a Tox save file; ignoring. + popup text + Es scheint, dass du eine Datei gewählt hast, die nicht zu Tox gehört. Sie wird erst einmal ignoriert. + + + + Profile already exists + import confirm title + Profil bereits vorhanden + + + + A profile named "%1" already exists. Do you want to erase it? + import confirm text + Ein Profil mit den Namen '%1' existiert bereits. Möchtest du es löschen? + + + + Save + save qr image + Bild speichern + + + + Save QrCode (*.png) + save dialog filter + QR-Code speichern (*.png) QObject - + Update The title of a message box - Update + Aktualisieren - + An update is available, do you want to download it now? It will be installed when qTox restarts. - Ein Update steht zur Verfügung, soll es heruntergeladen werden? -Es wird beim Neustart von qTox installiert. + Eine Aktualisierung für qTox ist verfügbar! Möchtest du sie jetzt herunterladen? +Sie wird bei einem Neustart installiert. - + + Resizing + Größe ändern + + + Tox URI to parse - Tox URI parsen + Zu parsende Tox URI - + Starts new instance and loads specified profile. - Startet eine neue Instanz und lädt das festgelegte Profil. + Startet eine neue Instanz und lädt das angegebene Profil. - + profile Profil - + Default Standard - + Blue Blau - + Olive Oliv - + Red Rot - + Violet Violett - - - Ignoring non-Tox file - popup title - Keine Toxdatei, wird ignoriert - - - - Warning: you've chosen a file that is not a Tox save file; ignoring. - popup text - Warnung: Sie haben eine Datei gewählt, die keine Toxdatei ist, wird ignoriert. - - - - Profile already exists - import confirm title - Profil existiert bereits - - - - A profile named "%1" already exists. Do you want to erase it? - import confirm text - Ein Profil mit dem Namen "%1" existiert bereits. Wollen Sie es löschen? - - - - Profile imported - Profil importiert - - - - %1.tox was successfully imported - %1.tox wurde erfolgreich importiert - - - - Tox me maybe? - Default message in Tox URI friend requests. Write something appropriate! - Lass uns toxen! - Incoming call... Eingehender Anruf... - - Busy... - + + Ignoring non-Tox file + popup title + Nicht-Tox Datei ignoriert + + + + Warning: you've chosen a file that is not a Tox save file; ignoring. + popup text + Es scheint, dass du eine Datei gewählt hast, die nicht zu Tox gehört. Sie wird erst einmal ignoriert. + + + + Profile already exists + import confirm title + Profil bereits vorhanden + + + + A profile named "%1" already exists. Do you want to erase it? + import confirm text + Entschuldige, aber ein Profil namens '%1' existiert bereits. Möchtest du es überschreiben? + + + + Profile imported + Profil importiert + + + + %1.tox was successfully imported + Die Datei %1.tox wurde erfolgreich importiert + + + + %1 here! Tox me maybe? + Default message in Tox URI friend requests. Write something appropriate! + Hallo, +Hier ist %1! Hast du Lust dich mit mir zu unterhalten? + +Viele Grüße +%1 @@ -1977,41 +1982,41 @@ Es wird beim Neustart von qTox installiert. Set your password - Passwort setzen - - - - Type password - Passwort eingeben + Setze dein Passwort Repeat password - Passwort wiederholen + Wiederholen + + + + Type password + Passwort Password strength - Passwortstärke + Stärke The passwords don't match. - Die Passwörter stimmen nicht überein. + Die eingegebenen Passwörter stimmen nicht überein. Settings - + Choose a profile - Wählen Sie ein Profil + Wähle ein Profil - + Please choose which identity to use - Wählen Sie die Identität, die benutzt werden soll + Bitte wähle ein Profil aus @@ -2020,7 +2025,7 @@ Es wird beim Neustart von qTox installiert. The connection timed out The DNS gives the Tox ID associated to toxme.se addresses - Zeitlimit der Verbindung überschritten + Eine Zeitüberschreitung in der Verbindung ist aufgetreten @@ -2032,38 +2037,38 @@ Es wird beim Neustart von qTox installiert. Error while looking up DNS The DNS gives the Tox ID associated to toxme.se addresses - Fehler beim Auflösen des DNS + Beim Nachschlagen der Adresse ist ein Fehler aufgetreten No text record found Error with the DNS - Kein Text Eintrag im DNS gefunden + Kein Texteintrag gefunden Unexpected number of values in text record Error with the DNS - Unerwartete Anzahl von Werten im Texteintrag + Unerwartete Anzahl an Einträgen in Text The version of Tox DNS used by this server is not supported Error with the DNS - Die Tox DNS Version dieses Servers wird nicht unterstützt + Die von diesem Server verwendete Version von Tox DNS wird leider nicht unterstützt The DNS lookup does not contain any Tox ID Error with the DNS - Der DNS Eintrag enthält keine Tox ID + Die ToxDNS Nachfrage konnte keine Tox ID finden The DNS lookup does not contain a valid Tox ID Error with the DNS - Der DNS Eintrag enthält keine gültige TOX ID + Die ToxDNS Nachfrage konnte keine gültige Tox ID finden @@ -2071,48 +2076,44 @@ Es wird beim Neustart von qTox installiert. It appears that qTox has to use the old tox1 protocol to access DNS record of your friend's Tox ID. Unfortunately tox1 is not secure, and you are at risk of someone hijacking what is sent between you and ToxDNS service. Should tox1 be used anyway? -If unsure, press “No”, so that request to ToxDNS service will not be made using unsecure protocol. - - - - It appears that qTox has to use the old tox1 protocol. -Unfortunately tox1 is not secure. Should it be used anyway? - Es scheint, dass qTox das veraltete tox1-Protokoll nutzen muss. -Dieses Protokoll ist nicht sicher. -Soll es dennoch genutzt werden? +If unsure, press “No”, so that request to ToxDNS service will not be made using unsecure protocol. + Es scheint, dass qTox ein altes Protokoll verwenden muss, um sich mit deinem Kontakt zu verbinden. +Leider ist die Alternativmethode nicht sicher und es besteht die Gefahr, dass an ToxDNS gesendete Daten abgefangen werden. +Soll das Alternativprotokoll trotzdem verwendet werden? +Falls du dir nicht sicher bist, wähle 'Nein'. ToxURIDialog - + Add a friend Title of the window to add a friend through Tox URI Einen Freund hinzufügen - + Do you want to add %1 as a friend? - Wollen Sie %1 als Freund hinzufügen? + Möchtest du %1 als Kontakt in deine Liste aufnehmen? - + User ID: - Benutzer ID: + ID: - + Friend request message: Freundschaftsanfrage: - + Send Send a friend request - Senden + Freundschaftsanfrage senden - + Cancel Don't send a friend request Abbrechen @@ -2121,167 +2122,134 @@ Soll es dennoch genutzt werden? Widget - Online - Online - - - Away - Abwesend - - - Busy - Beschäftigt - - - - &Quit - &Beenden - - - Change status to: - Ändert den Status in: - - - + Online Button to set your status to 'Online' Online - + Away Button to set your status to 'Away' Abwesend - + Busy Button to set your status to 'Busy' Beschäftigt - Choose a profile - Wählen Sie ein Profil - - - Please choose which identity to use - Wählen Sie die Identität, die benutzt werden soll - - - - Choose a profile picture - Wählen Sie ein Profilbild - - - - - - Error - Fehler - - - - Unable to open this file - Kann diese Datei nicht öffnen - - - - Unable to read this image - Kann dieses Bild nicht einlesen - - - - This image is too big - Dieses Bild ist zu groß - - - + Toxcore failed to start, the application will terminate after you close this message. - Tox startet nicht, die Anwendung wird nach Schließen dieses Fensters beendet. + Entschuldige, es ist ein Fehler aufgetreten und die Anwendung lässt sich nicht starten. - + toxcore failed to start with your proxy settings. qTox cannot run; please modify your settings and restart. popup text - Tox startet nicht mit ihren Proxy-Einstellungen. qTox funktioniert nicht, ändern Sie bitte Ihre Einstellungen und starten qTox neu. + Entschuldige, es ist ein Fehler aufgetreten und die Anwendung kann nicht gestartet werden. +Leider führen deine Proxyeinstellungen zu Problemen. Bitte ändere deine Einstellungen und versuche es erneut. - + Add friend - Freund hinzufügen + Einen Freund hinzufügen - + File transfers Dateiübertragungen - + + Executable file + popup title + Ausführbare Datei + + + + 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 + Du hast qTox aufgefordert eine Datei auszuführen. Bitte beachte, dass ausführbare Dateien ein Sicherheitsrisiko darstellen können. Bist du dir sicher, dass du die Datei ausführen möchtest? + + + Settings Einstellungen - - Couldn't request friendship - Freundschaftsanfrage fehlgeschlagen + + Profile + Profil - + + Couldn't request friendship + Freundschaftsanfrage konnte nicht gesendet werden + + + away contact status Abwesend - + busy contact status Beschäftigt - + offline contact status Offline - + online contact status Online - + %1 is now %2 e.g. "Dubslow is now online" - %1 ist nun %2 + %1 ist jetzt %2 - + Group invite popup title - + Gruppeneinladung - + %1 has invited you to a groupchat. Would you like to join? popup text - + %1 hat dich in eine Gruppe eingeladen! Möchtest du ihr beitreten? - + <Unknown> Placeholder when we don't know someone's name in a group chat <Unbekannt> - + %1 has set the title to %2 %1 hat den Titel auf %2 gesetzt - + + &Quit + Beenden + + + Message failed to send - Senden der Nachricht fehlgeschlagen + Nachricht konnte nicht gesendet werden From 43279368f3ba9e4fe6ed40ac107c207290159285 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 22:57:02 +0200 Subject: [PATCH 36/51] Cherry-pick da084594d9b58a5cbaf2414efecac04700c72ab4 from #1523 Closes #1523 From cdf3d9f553b986b733c05fcebe2f224f7be67be1 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 24 Apr 2015 23:05:44 +0200 Subject: [PATCH 37/51] Change some tabs to space for consistency --- src/video/cameraworker.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/video/cameraworker.cpp b/src/video/cameraworker.cpp index e972ef58d..b3836810c 100644 --- a/src/video/cameraworker.cpp +++ b/src/video/cameraworker.cpp @@ -37,14 +37,14 @@ CameraWorker::~CameraWorker() void CameraWorker::onStart() { - if (!clock) - { - clock = new QTimer(this); - clock->setSingleShot(false); - clock->setInterval(1000/60); + if (!clock) + { + clock = new QTimer(this); + clock->setSingleShot(false); + clock->setInterval(1000/60); - connect(clock, &QTimer::timeout, this, &CameraWorker::doWork); - } + connect(clock, &QTimer::timeout, this, &CameraWorker::doWork); + } emit started(); } From 9d3d17d05e379b0b65f8430396a575e6a0db4634 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 25 Apr 2015 01:26:52 +0200 Subject: [PATCH 38/51] Avatar sending on top of file transfers --- src/core/core.cpp | 41 +++----------- src/core/corefile.cpp | 124 ++++++++++++++++++++++++++++++++++------- src/core/corefile.h | 1 + src/core/corestructs.h | 1 + 4 files changed, 115 insertions(+), 52 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index ebe45087d..5248c9d74 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -484,39 +484,16 @@ void Core::onConnectionStatusChanged(Tox*/* tox*/, uint32_t friendId, TOX_CONNEC if (friendStatus == Status::Offline) { static_cast(core)->checkLastOnline(friendId); - - /** TODO: Review file sending breaking/resuming - for (ToxFile& f : fileSendQueue) - { - if (f.friendId == friendId && f.status == ToxFile::TRANSMITTING) - { - f.status = ToxFile::BROKEN; - emit static_cast(core)->fileTransferBrokenUnbroken(f, true); - } - } - for (ToxFile& f : fileRecvQueue) - { - if (f.friendId == friendId && f.status == ToxFile::TRANSMITTING) - { - f.status = ToxFile::BROKEN; - emit static_cast(core)->fileTransferBrokenUnbroken(f, true); - } - } - */ } else { - /** - for (ToxFile& f : fileRecvQueue) - { - if (f.friendId == friendId && f.status == ToxFile::BROKEN) - { - qDebug() << QString("Core::onConnectionStatusChanged: %1: resuming broken filetransfer from position: %2").arg(f.file->fileName()).arg(f.bytesSent); - tox_file_control(static_cast(core)->tox, friendId, f.fileNum, TOX_FILE_CONTROL_RESUME, nullptr); - emit static_cast(core)->fileTransferBrokenUnbroken(f, false); - } - } - */ + QPixmap pic = Settings::getInstance().getSavedAvatar(static_cast(core)->getSelfId().toString()); + QByteArray bytes; + QBuffer buffer(&bytes); + buffer.open(QIODevice::WriteOnly); + pic.save(&buffer, "PNG"); + buffer.close(); + CoreFile::sendAvatarFile(static_cast(core), friendId, bytes); } } @@ -772,8 +749,6 @@ void Core::setUsername(const QString& username) void Core::setAvatar(const QByteArray& data) { - /// TODO: Review this function, toxcore doesn't handle avatars anymore apparently. Good. - QPixmap pic; pic.loadFromData(data); Settings::getInstance().saveAvatar(pic, getSelfId().toString()); @@ -783,7 +758,7 @@ void Core::setAvatar(const QByteArray& data) // according to tox.h, we need not broadcast this ourselves, but initial testing indicated elsewise const uint32_t friendCount = tox_self_get_friend_list_size(tox); for (unsigned i=0; i #include #include +#include #include QMutex CoreFile::fileSendMutex; QHash CoreFile::fileMap; using namespace std; +void CoreFile::sendAvatarFile(Core* core, uint32_t friendId, const QByteArray& data) +{ + QMutexLocker mlocker(&fileSendMutex); + + uint8_t filename[TOX_HASH_LENGTH]; + tox_hash(filename, (uint8_t*)data.data(), data.size()); + uint64_t filesize = data.size(); + uint32_t fileNum = tox_file_send(core->tox, friendId, TOX_FILE_KIND_AVATAR, filesize, + nullptr, filename, TOX_HASH_LENGTH, nullptr); + if (fileNum == UINT32_MAX) + { + qWarning() << "CoreFile::sendAvatarFile: Can't create the Tox file sender"; + return; + } + qDebug() << QString("CoreFile::sendAvatarFile: Created file sender %1 with friend %2").arg(fileNum).arg(friendId); + + ToxFile file{fileNum, friendId, "", "", ToxFile::SENDING}; + file.filesize = filesize; + file.fileName = QByteArray((char*)filename, TOX_HASH_LENGTH); + file.fileKind = TOX_FILE_KIND_AVATAR; + file.avatarData = data; + addFile(friendId, fileNum, file); +} + void CoreFile::sendFile(Core* core, uint32_t friendId, QString Filename, QString FilePath, long long filesize) { QMutexLocker mlocker(&fileSendMutex); @@ -175,18 +201,43 @@ void CoreFile::removeFile(uint32_t friendId, uint32_t fileId) } void CoreFile::onFileReceiveCallback(Tox*, uint32_t friendId, uint32_t fileId, uint32_t kind, - uint64_t filesize, const uint8_t *fname, size_t fnameLen, void *core) + uint64_t filesize, const uint8_t *fname, size_t fnameLen, void *_core) { + Core* core = static_cast(_core); qDebug() << QString("CoreFile: Received file request %1:%2 kind %3") .arg(friendId).arg(fileId).arg(kind); + if (kind == TOX_FILE_KIND_AVATAR) + { + QString friendAddr = core->getFriendAddress(friendId); + if (!filesize) + { + // Avatars of size 0 means explicitely no avatar + emit core->friendAvatarRemoved(friendId); + QFile::remove(QDir(Settings::getSettingsDirPath()).filePath("avatars/"+friendAddr.left(64)+".png")); + QFile::remove(QDir(Settings::getSettingsDirPath()).filePath("avatars/"+friendAddr.left(64)+".hash")); + return; + } + else if (Settings::getInstance().getAvatarHash(friendAddr) == QByteArray((char*)fname, fnameLen)) + { + // If it's an avatar but we already have it cached, cancel + tox_file_control(core->tox, friendId, fileId, TOX_FILE_CONTROL_CANCEL, nullptr); + return; + } + else + { + // It's an avatar and we don't have it, autoaccept the transfer + tox_file_control(core->tox, friendId, fileId, TOX_FILE_CONTROL_RESUME, nullptr); + } + } + ToxFile file{fileId, friendId, CString::toString(fname,fnameLen).toUtf8(), "", ToxFile::RECEIVING}; file.filesize = filesize; file.fileKind = kind; addFile(friendId, fileId, file); - if (kind == TOX_FILE_KIND_DATA) - emit static_cast(core)->fileReceiveRequested(file); + if (kind != TOX_FILE_KIND_AVATAR) + emit core->fileReceiveRequested(file); } void CoreFile::onFileControlCallback(Tox*, uint32_t friendId, uint32_t fileId, TOX_FILE_CONTROL control, void *core) @@ -238,31 +289,43 @@ void CoreFile::onFileDataCallback(Tox *tox, uint32_t friendId, uint32_t fileId, if (!length) { qDebug("CoreFile::onFileDataCallback: File sending completed"); - emit static_cast(core)->fileTransferFinished(*file); + if (file->fileKind != TOX_FILE_KIND_AVATAR) + emit static_cast(core)->fileTransferFinished(*file); removeFile(friendId, fileId); return; } unique_ptr data(new uint8_t[length]); + int64_t nread; - file->file->seek(pos); - int64_t nread = file->file->read((char*)data.get(), length); - if (nread <= 0) + if (file->fileKind == TOX_FILE_KIND_AVATAR) { - qWarning("CoreFile::onFileDataCallback: Failed to read from file"); - emit static_cast(core)->fileTransferCancelled(*file); - tox_file_send_chunk(tox, friendId, fileId, pos, nullptr, 0, nullptr); - removeFile(friendId, fileId); - return; + QByteArray chunk = file->avatarData.mid(pos, length); + nread = chunk.size(); + memcpy(data.get(), chunk.data(), nread); + } + else + { + file->file->seek(pos); + nread = file->file->read((char*)data.get(), length); + if (nread <= 0) + { + qWarning("CoreFile::onFileDataCallback: Failed to read from file"); + emit static_cast(core)->fileTransferCancelled(*file); + tox_file_send_chunk(tox, friendId, fileId, pos, nullptr, 0, nullptr); + removeFile(friendId, fileId); + return; + } + file->bytesSent += length; } - file->bytesSent += length; if (!tox_file_send_chunk(tox, friendId, fileId, pos, data.get(), nread, nullptr)) { qWarning("CoreFile::onFileDataCallback: Failed to send data chunk"); return; } - emit static_cast(core)->fileTransferInfo(*file); + if (file->fileKind != TOX_FILE_KIND_AVATAR) + emit static_cast(core)->fileTransferInfo(*file); } void CoreFile::onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fileId, uint64_t position, @@ -282,17 +345,40 @@ void CoreFile::onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fil { /// TODO: Allow ooo receiving for non-stream transfers, with very careful checking qWarning("CoreFile::onFileRecvChunkCallback: Received a chunk out-of-order, aborting transfer"); - emit static_cast(core)->fileTransferCancelled(*file); + if (file->fileKind != TOX_FILE_KIND_AVATAR) + emit static_cast(core)->fileTransferCancelled(*file); tox_file_control(tox, friendId, fileId, TOX_FILE_CONTROL_CANCEL, nullptr); removeFile(friendId, fileId); return; } + + if (file->fileKind == TOX_FILE_KIND_AVATAR) + file->avatarData.append((char*)data, length); + else + file->file->write((char*)data,length); file->bytesSent += length; - file->file->write((char*)data,length); - //qDebug() << QString("CoreFile::onFileRecvChunkCallback: received %1/%2 bytes").arg(file->bytesSent).arg(file->filesize); if (file->bytesSent == file->filesize) - emit static_cast(core)->fileTransferFinished(*file); - else + { + if (file->fileKind == TOX_FILE_KIND_AVATAR) + { + QPixmap pic; + pic.loadFromData(file->avatarData); + if (!pic.isNull()) + { + qDebug() << "Core: Got avatar data from" << static_cast(core)->getFriendUsername(friendId); + Settings::getInstance().saveAvatar(pic, static_cast(core)->getFriendAddress(friendId)); + Settings::getInstance().saveAvatarHash(file->fileName, static_cast(core)->getFriendAddress(friendId)); + emit static_cast(core)->friendAvatarChanged(friendId, pic); + } + } + else + { + emit static_cast(core)->fileTransferFinished(*file); + } + } + else if (file->fileKind != TOX_FILE_KIND_AVATAR) + { emit static_cast(core)->fileTransferInfo(*file); + } } diff --git a/src/core/corefile.h b/src/core/corefile.h index cf8816524..1a7a03033 100644 --- a/src/core/corefile.h +++ b/src/core/corefile.h @@ -26,6 +26,7 @@ private: private: static void sendFile(Core *core, uint32_t friendId, QString Filename, QString FilePath, long long filesize); + static void sendAvatarFile(Core* core, uint32_t friendId, const QByteArray& data); static void pauseResumeFileSend(Core* core, uint32_t friendId, uint32_t fileId); static void pauseResumeFileRecv(Core* core, uint32_t friendId, uint32_t fileId); static void cancelFileSend(Core* core, uint32_t friendId, uint32_t fileId); diff --git a/src/core/corestructs.h b/src/core/corestructs.h index fc16c852e..c6eb12896 100644 --- a/src/core/corestructs.h +++ b/src/core/corestructs.h @@ -78,6 +78,7 @@ struct ToxFile FileStatus status; FileDirection direction; QTimer* sendTimer; + QByteArray avatarData; }; #endif // CORESTRUCTS_H From 0e65d150e3994f5e4e6a982b64b142b6fb9cc228 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 25 Apr 2015 01:50:35 +0200 Subject: [PATCH 39/51] Don't show call buttons in text-only groupchats I'm not sure why there are text-only groupchats in the first place, but that's fixed. --- src/core/core.cpp | 5 +++++ src/core/core.h | 2 ++ src/widget/widget.cpp | 5 +++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 5248c9d74..bb155d411 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -1147,6 +1147,11 @@ void Core::createGroup(uint8_t type) } } +bool Core::isGroupAvEnabled(int groupId) +{ + return tox_group_get_type(tox, groupId) == TOX_GROUPCHAT_TYPE_AV; +} + bool Core::hasFriendWithAddress(const QString &addr) const { // Valid length check diff --git a/src/core/core.h b/src/core/core.h index 32105b29e..494ac788b 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -131,6 +131,8 @@ public slots: void setNospam(uint32_t nospam); + bool isGroupAvEnabled(int groupId); ///< True for AV groups, false for text-only groups + static void joinGroupCall(int groupId); ///< Starts a call in an existing AV groupchat. Call from the GUI thread. static void leaveGroupCall(int groupId); ///< Will not leave the group, just stop the call. Call from the GUI thread. static void disableGroupCallMic(int groupId); diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 63030483e..babe5d28d 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -994,13 +994,14 @@ Group *Widget::createGroup(int groupId) return g; } + Core* core = Nexus::getCore(); + QString groupName = QString("Groupchat #%1").arg(groupId); - Group* newgroup = GroupList::addGroup(groupId, groupName, true); + Group* newgroup = GroupList::addGroup(groupId, groupName, core->isGroupAvEnabled(groupId)); QLayout* layout = contactListWidget->getGroupLayout(); layout->addWidget(newgroup->getGroupWidget()); newgroup->getGroupWidget()->updateStatusLight(); - Core* core = Nexus::getCore(); connect(settingsWidget, &SettingsWidget::compactToggled, newgroup->getGroupWidget(), &GenericChatroomWidget::onCompactChanged); connect(newgroup->getGroupWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*)), this, SLOT(onChatroomWidgetClicked(GenericChatroomWidget*))); connect(newgroup->getGroupWidget(), SIGNAL(removeGroup(int)), this, SLOT(removeGroup(int))); From 9ece486e2247a44e77389a80ca42d93233b07466 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 25 Apr 2015 02:28:47 +0200 Subject: [PATCH 40/51] Prevent possible uninitialized read of status For unhandled values of Status, we want to return, not continue with an uninitialized value. --- src/core/core.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/core.cpp b/src/core/core.cpp index bb155d411..cdbb49169 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -830,6 +830,7 @@ void Core::setStatus(Status status) userstatus = TOX_USER_STATUS_BUSY; break; default: + return; break; } From bd5eebbc2efb960428dad26fb5de2b76969faf53 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 25 Apr 2015 16:51:58 +0200 Subject: [PATCH 41/51] Cache avatar sending, fix image file preview - Add AvatarBroadcaster, in charge of making sure our friends have our avatar without spamming file transfers - Fix file sending code not closing the file after transfer, which prevented file previews, and make the QFile a shared_ptr to fix the obvious memory leak Some small additions to Core to support AvatarBroadcaster --- qtox.pro | 6 ++++-- src/avatarbroadcaster.cpp | 41 +++++++++++++++++++++++++++++++++++++++ src/avatarbroadcaster.h | 28 ++++++++++++++++++++++++++ src/core/core.cpp | 40 +++++++++++++++++++++----------------- src/core/core.h | 15 ++++++++------ src/core/corefile.cpp | 33 ++++++++++++++++++------------- src/core/corestructs.h | 3 ++- 7 files changed, 126 insertions(+), 40 deletions(-) create mode 100644 src/avatarbroadcaster.cpp create mode 100644 src/avatarbroadcaster.h diff --git a/qtox.pro b/qtox.pro index 2856df7d4..674026cbf 100644 --- a/qtox.pro +++ b/qtox.pro @@ -430,7 +430,8 @@ SOURCES += \ src/core/coreencryption.cpp \ src/core/corefile.cpp \ src/core/corestructs.cpp \ - src/profilelocker.cpp + src/profilelocker.cpp \ + src/avatarbroadcaster.cpp HEADERS += \ src/audio.h \ @@ -455,4 +456,5 @@ HEADERS += \ src/widget/gui.h \ src/toxme.h \ src/misc/qrwidget.h \ - src/profilelocker.h + src/profilelocker.h \ + src/avatarbroadcaster.h diff --git a/src/avatarbroadcaster.cpp b/src/avatarbroadcaster.cpp new file mode 100644 index 000000000..fc8462975 --- /dev/null +++ b/src/avatarbroadcaster.cpp @@ -0,0 +1,41 @@ +#include "avatarbroadcaster.h" +#include "src/core/core.h" +#include +#include + +QByteArray AvatarBroadcaster::avatarData; +QMap AvatarBroadcaster::friendsSentTo; + +static QMetaObject::Connection autoBroadcastConn; +static auto autoBroadcast = [](uint32_t friendId, Status) +{ + AvatarBroadcaster::sendAvatarTo(friendId); +}; + +void AvatarBroadcaster::setAvatar(QByteArray data) +{ + avatarData = data; + friendsSentTo.clear(); + + QVector friends = Core::getInstance()->getFriendList(); + for (uint32_t friendId : friends) + sendAvatarTo(friendId); +} + +void AvatarBroadcaster::sendAvatarTo(uint32_t friendId) +{ + if (friendsSentTo.contains(friendId) && friendsSentTo[friendId]) + return; + if (!Core::getInstance()->isFriendOnline(friendId)) + return; + qDebug() << "AvatarBroadcaster: Sending avatar to "<sendAvatarFile(friendId, avatarData); + friendsSentTo[friendId] = true; +} + +void AvatarBroadcaster::enableAutoBroadcast(bool state) +{ + QObject::disconnect(autoBroadcastConn); + if (state) + autoBroadcastConn = QObject::connect(Core::getInstance(), &Core::friendStatusChanged, autoBroadcast); +} diff --git a/src/avatarbroadcaster.h b/src/avatarbroadcaster.h new file mode 100644 index 000000000..ce0a3b218 --- /dev/null +++ b/src/avatarbroadcaster.h @@ -0,0 +1,28 @@ +#ifndef AVATARBROADCASTER_H +#define AVATARBROADCASTER_H + +#include +#include + +/// 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: + AvatarBroadcaster()=delete; + +public: + /// Set our current avatar + static void setAvatar(QByteArray data); + /// Send our current avatar to this friend, if not already sent + static void sendAvatarTo(uint32_t friendId); + /// If true, we automatically broadcast our avatar to friends when they come online + static void enableAutoBroadcast(bool state = true); + +private: + static QByteArray avatarData; + static QMap friendsSentTo; +}; + +#endif // AVATARBROADCASTER_H diff --git a/src/core/core.cpp b/src/core/core.cpp index cdbb49169..f90d40417 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -23,6 +23,7 @@ #include "src/historykeeper.h" #include "src/audio.h" #include "src/profilelocker.h" +#include "src/avatarbroadcaster.h" #include "corefile.h" #include @@ -479,22 +480,10 @@ void Core::onUserStatusChanged(Tox*/* tox*/, uint32_t friendId, TOX_USER_STATUS void Core::onConnectionStatusChanged(Tox*/* tox*/, uint32_t friendId, TOX_CONNECTION status, void* core) { - Status friendStatus = status ? Status::Online : Status::Offline; + Status friendStatus = status != TOX_CONNECTION_NONE ? Status::Online : Status::Offline; emit static_cast(core)->friendStatusChanged(friendId, friendStatus); if (friendStatus == Status::Offline) - { static_cast(core)->checkLastOnline(friendId); - } - else - { - QPixmap pic = Settings::getInstance().getSavedAvatar(static_cast(core)->getSelfId().toString()); - QByteArray bytes; - QBuffer buffer(&bytes); - buffer.open(QIODevice::WriteOnly); - pic.save(&buffer, "PNG"); - buffer.close(); - CoreFile::sendAvatarFile(static_cast(core), friendId, bytes); - } } void Core::onGroupAction(Tox*, int groupnumber, int peernumber, const uint8_t *action, uint16_t length, void* _core) @@ -664,6 +653,11 @@ void Core::sendFile(uint32_t friendId, QString Filename, QString FilePath, long CoreFile::sendFile(this, friendId, Filename, FilePath, filesize); } +void Core::sendAvatarFile(uint32_t friendId, const QByteArray& data) +{ + CoreFile::sendAvatarFile(this, friendId, data); +} + void Core::pauseResumeFileSend(uint32_t friendId, uint32_t fileNum) { CoreFile::pauseResumeFileSend(this, friendId, fileNum); @@ -754,11 +748,8 @@ void Core::setAvatar(const QByteArray& data) Settings::getInstance().saveAvatar(pic, getSelfId().toString()); emit selfAvatarChanged(pic); - // Broadcast our new avatar! - // according to tox.h, we need not broadcast this ourselves, but initial testing indicated elsewise - const uint32_t friendCount = tox_self_get_friend_list_size(tox); - for (unsigned i=0; i Core::getFriendList() const +{ + QVector friends; + friends.resize(tox_self_get_friend_list_size(tox)); + tox_self_get_friend_list(tox, friends.data()); + return friends; +} + int Core::getGroupNumberPeers(int groupId) const { return tox_group_number_peers(tox, groupId); @@ -1153,6 +1152,11 @@ bool Core::isGroupAvEnabled(int groupId) return tox_group_get_type(tox, groupId) == TOX_GROUPCHAT_TYPE_AV; } +bool Core::isFriendOnline(uint32_t friendId) const +{ + return tox_friend_get_connection_status(tox, friendId, nullptr) != TOX_CONNECTION_NONE; +} + bool Core::hasFriendWithAddress(const QString &addr) const { // Valid length check diff --git a/src/core/core.h b/src/core/core.h index 494ac788b..4d694ead5 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -57,15 +57,17 @@ public: QString getPeerName(const ToxID& id) const; + QVector getFriendList() const; ///< Returns the list of friendIds in our friendlist, an empty list on error int getGroupNumberPeers(int groupId) const; ///< Return the number of peers in the group chat on success, or -1 on failure QString getGroupPeerName(int groupId, int peerId) const; ///< Get the name of a peer of a group ToxID getGroupPeerToxID(int groupId, int peerId) const; ///< Get the ToxID of a peer of a group QList getGroupPeerNames(int groupId) const; ///< Get the names of the peers of a group - QString getFriendAddress(uint32_t friendNumber) const; ///< Get the full address if known, or Tox ID of a friend - QString getFriendUsername(uint32_t friendNumber) const; ///< Get the username of a friend + QString getFriendAddress(uint32_t friendId) const; ///< Get the full address if known, or Tox ID of a friend + QString getFriendUsername(uint32_t friendId) const; ///< Get the username of a friend + bool isFriendOnline(uint32_t friendId) const; ///< Check if a friend is online. Unknown friends are considered offline. bool hasFriendWithAddress(const QString &addr) const; ///< Check if we have a friend by address bool hasFriendWithPublicKey(const QString &pubkey) const; ///< Check if we have a friend by public key - int joinGroupchat(int32_t friendNumber, uint8_t type, const uint8_t* pubkey,uint16_t length) const; ///< Accept a groupchat invite + int joinGroupchat(int32_t friendId, uint8_t type, const uint8_t* pubkey,uint16_t length) const; ///< Accept a groupchat invite void quitGroupChat(int groupId) const; ///< Quit a groupchat QString getIDString() const; ///< Get the 12 first characters of our Tox ID @@ -113,6 +115,7 @@ public slots: void sendTyping(uint32_t friendId, bool typing); void sendFile(uint32_t friendId, QString Filename, QString FilePath, long long filesize); + void sendAvatarFile(uint32_t friendId, const QByteArray& data); void cancelFileSend(uint32_t friendId, uint32_t fileNum); void cancelFileRecv(uint32_t friendId, uint32_t fileNum); void rejectFileRecvRequest(uint32_t friendId, uint32_t fileNum); @@ -170,7 +173,7 @@ signals: void friendLastSeenChanged(uint32_t friendId, const QDateTime& dateTime); void emptyGroupCreated(int groupnumber); - void groupInviteReceived(uint32_t friendNumber, uint8_t type, QByteArray publicKey); + void groupInviteReceived(uint32_t friendId, uint8_t type, QByteArray publicKey); void groupMessageReceived(int groupnumber, int peernumber, const QString& message, bool isAction); void groupNamelistChanged(int groupnumber, int peernumber, uint8_t change); void groupTitleChanged(int groupnumber, const QString& author, const QString& title); @@ -241,14 +244,14 @@ private: static void onConnectionStatusChanged(Tox* tox, uint32_t friendId, TOX_CONNECTION status, void* core); static void onGroupAction(Tox* tox, int groupnumber, int peernumber, const uint8_t * action, uint16_t length, void* core); - static void onGroupInvite(Tox *tox, int32_t friendNumber, uint8_t type, const uint8_t *data, + static void onGroupInvite(Tox *tox, int32_t friendId, uint8_t type, const uint8_t *data, uint16_t length, void *userdata); static void onGroupMessage(Tox *tox, int groupnumber, int friendgroupnumber, const uint8_t * message, uint16_t length, void *userdata); static void onGroupNamelistChange(Tox *tox, int groupId, int peerId, uint8_t change, void *core); static void onGroupTitleChange(Tox*, int groupnumber, int peernumber, const uint8_t* title, uint8_t len, void* _core); - static void onReadReceiptCallback(Tox *tox, uint32_t friendnumber, uint32_t receipt, void *core); + static void onReadReceiptCallback(Tox *tox, uint32_t friendId, uint32_t receipt, void *core); static void onAvInvite(void* toxav, int32_t call_index, void* core); static void onAvStart(void* toxav, int32_t call_index, void* core); diff --git a/src/core/corefile.cpp b/src/core/corefile.cpp index a5b5e1deb..ad06c5de2 100644 --- a/src/core/corefile.cpp +++ b/src/core/corefile.cpp @@ -178,7 +178,7 @@ ToxFile* CoreFile::findFile(uint32_t friendId, uint32_t fileId) uint64_t key = ((uint64_t)friendId<<32) + (uint64_t)fileId; if (!fileMap.contains(key)) { - qWarning() << "CoreFile::addFile: File transfer with ID "<close(); + fileMap.remove(key); } void CoreFile::onFileReceiveCallback(Tox*, uint32_t friendId, uint32_t fileId, uint32_t kind, @@ -331,7 +336,8 @@ void CoreFile::onFileDataCallback(Tox *tox, uint32_t friendId, uint32_t fileId, void CoreFile::onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fileId, uint64_t position, const uint8_t *data, size_t length, void *core) { - //qDebug() << QString("CoreFile: Received file chunk for request %1:%2").arg(friendId).arg(fileId); + qDebug() << QString("CoreFile: Received chunk for %1:%2 pos %3 size %4") + .arg(friendId).arg(fileId).arg(position).arg(length); ToxFile* file = findFile(friendId, fileId); if (!file) @@ -352,13 +358,7 @@ void CoreFile::onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fil return; } - if (file->fileKind == TOX_FILE_KIND_AVATAR) - file->avatarData.append((char*)data, length); - else - file->file->write((char*)data,length); - file->bytesSent += length; - - if (file->bytesSent == file->filesize) + if (!length) { if (file->fileKind == TOX_FILE_KIND_AVATAR) { @@ -376,9 +376,16 @@ void CoreFile::onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fil { emit static_cast(core)->fileTransferFinished(*file); } + removeFile(friendId, fileId); + return; } - else if (file->fileKind != TOX_FILE_KIND_AVATAR) - { + + if (file->fileKind == TOX_FILE_KIND_AVATAR) + file->avatarData.append((char*)data, length); + else + file->file->write((char*)data,length); + file->bytesSent += length; + + if (file->fileKind != TOX_FILE_KIND_AVATAR) emit static_cast(core)->fileTransferInfo(*file); - } } diff --git a/src/core/corestructs.h b/src/core/corestructs.h index c6eb12896..388b94366 100644 --- a/src/core/corestructs.h +++ b/src/core/corestructs.h @@ -5,6 +5,7 @@ // They should include this file directly instead to reduce compilation times #include +#include class QFile; class QTimer; @@ -72,7 +73,7 @@ struct ToxFile uint32_t friendId; QByteArray fileName; QString filePath; - QFile* file; + std::shared_ptr file; quint64 bytesSent; quint64 filesize; FileStatus status; From c6e60c4c77c4341d7aa19be650208120795e0ebd Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 25 Apr 2015 16:59:29 +0200 Subject: [PATCH 42/51] Remove some CoreFile debug output --- src/core/corefile.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/corefile.cpp b/src/core/corefile.cpp index ad06c5de2..99cccf34f 100644 --- a/src/core/corefile.cpp +++ b/src/core/corefile.cpp @@ -27,7 +27,7 @@ void CoreFile::sendAvatarFile(Core* core, uint32_t friendId, const QByteArray& d qWarning() << "CoreFile::sendAvatarFile: Can't create the Tox file sender"; return; } - qDebug() << QString("CoreFile::sendAvatarFile: Created file sender %1 with friend %2").arg(fileNum).arg(friendId); + //qDebug() << QString("CoreFile::sendAvatarFile: Created file sender %1 with friend %2").arg(fileNum).arg(friendId); ToxFile file{fileNum, friendId, "", "", ToxFile::SENDING}; file.filesize = filesize; @@ -293,7 +293,7 @@ void CoreFile::onFileDataCallback(Tox *tox, uint32_t friendId, uint32_t fileId, // If we reached EOF, ack and cleanup the transfer if (!length) { - qDebug("CoreFile::onFileDataCallback: File sending completed"); + //qDebug("CoreFile::onFileDataCallback: File sending completed"); if (file->fileKind != TOX_FILE_KIND_AVATAR) emit static_cast(core)->fileTransferFinished(*file); removeFile(friendId, fileId); @@ -336,8 +336,8 @@ void CoreFile::onFileDataCallback(Tox *tox, uint32_t friendId, uint32_t fileId, void CoreFile::onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fileId, uint64_t position, const uint8_t *data, size_t length, void *core) { - qDebug() << QString("CoreFile: Received chunk for %1:%2 pos %3 size %4") - .arg(friendId).arg(fileId).arg(position).arg(length); + //qDebug() << QString("CoreFile: Received chunk for %1:%2 pos %3 size %4") + // .arg(friendId).arg(fileId).arg(position).arg(length); ToxFile* file = findFile(friendId, fileId); if (!file) From cdb2bad7c3a07d4e8c1f534d8a7d10b776ccd74a Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 25 Apr 2015 17:12:49 +0200 Subject: [PATCH 43/51] Signal broken file transfers --- src/core/core.cpp | 1 + src/core/corefile.cpp | 12 ++++++++++++ src/core/corefile.h | 1 + 3 files changed, 14 insertions(+) diff --git a/src/core/core.cpp b/src/core/core.cpp index f90d40417..7a458d6dc 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -484,6 +484,7 @@ void Core::onConnectionStatusChanged(Tox*/* tox*/, uint32_t friendId, TOX_CONNEC emit static_cast(core)->friendStatusChanged(friendId, friendStatus); if (friendStatus == Status::Offline) static_cast(core)->checkLastOnline(friendId); + CoreFile::onConnectionStatusChanged(static_cast(core), friendId, friendStatus != Status::Offline); } void Core::onGroupAction(Tox*, int groupnumber, int peernumber, const uint8_t *action, uint16_t length, void* _core) diff --git a/src/core/corefile.cpp b/src/core/corefile.cpp index 99cccf34f..299df352a 100644 --- a/src/core/corefile.cpp +++ b/src/core/corefile.cpp @@ -389,3 +389,15 @@ void CoreFile::onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fil if (file->fileKind != TOX_FILE_KIND_AVATAR) emit static_cast(core)->fileTransferInfo(*file); } + +void CoreFile::onConnectionStatusChanged(Core* core, uint32_t friendId, bool online) +{ + ToxFile::FileStatus status = online ? ToxFile::TRANSMITTING : ToxFile::BROKEN; + for (uint64_t key : fileMap.keys()) + { + if (key>>32 != friendId) + continue; + fileMap[key].status = status; + emit core->fileTransferBrokenUnbroken(fileMap[key], !online); + } +} diff --git a/src/core/corefile.h b/src/core/corefile.h index 1a7a03033..9588bb545 100644 --- a/src/core/corefile.h +++ b/src/core/corefile.h @@ -46,6 +46,7 @@ private: uint64_t pos, size_t length, void *core); static void onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fileId, uint64_t position, const uint8_t *data, size_t length, void *core); + static void onConnectionStatusChanged(Core* core, uint32_t friendId, bool online); private: static QMutex fileSendMutex; From e74e29e4fb172002567e6e759405aeb7f5906aad Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 25 Apr 2015 19:18:46 +0200 Subject: [PATCH 44/51] Cleanly cancel broken file transfers --- src/chatlog/content/filetransferwidget.cpp | 8 ++++++++ src/chatlog/content/filetransferwidget.h | 1 + src/core/corefile.cpp | 12 ++++++++++++ src/core/corestructs.h | 1 + 4 files changed, 22 insertions(+) diff --git a/src/chatlog/content/filetransferwidget.cpp b/src/chatlog/content/filetransferwidget.cpp index 636874fd3..1888a229c 100644 --- a/src/chatlog/content/filetransferwidget.cpp +++ b/src/chatlog/content/filetransferwidget.cpp @@ -78,6 +78,7 @@ FileTransferWidget::FileTransferWidget(QWidget *parent, ToxFile file) connect(Core::getInstance(), &Core::fileTransferPaused, this, &FileTransferWidget::onFileTransferPaused); connect(Core::getInstance(), &Core::fileTransferFinished, this, &FileTransferWidget::onFileTransferFinished); connect(Core::getInstance(), &Core::fileTransferRemotePausedUnpaused, this, &FileTransferWidget::fileTransferRemotePausedUnpaused); + connect(Core::getInstance(), &Core::fileTransferBrokenUnbroken, this, &FileTransferWidget::fileTransferBrokenUnbroken); setupButtons(); @@ -370,6 +371,13 @@ void FileTransferWidget::fileTransferRemotePausedUnpaused(ToxFile file, bool pau onFileTransferResumed(file); } +void FileTransferWidget::fileTransferBrokenUnbroken(ToxFile file, bool broken) +{ + /// TODO: Handle broken transfer differently once we have resuming code + if (broken) + onFileTransferCancelled(file); +} + QString FileTransferWidget::getHumanReadableSize(qint64 size) { static const char* suffix[] = {"B","kiB","MiB","GiB","TiB"}; diff --git a/src/chatlog/content/filetransferwidget.h b/src/chatlog/content/filetransferwidget.h index 491477345..b05a3aee5 100644 --- a/src/chatlog/content/filetransferwidget.h +++ b/src/chatlog/content/filetransferwidget.h @@ -48,6 +48,7 @@ protected slots: void onFileTransferResumed(ToxFile file); void onFileTransferFinished(ToxFile file); void fileTransferRemotePausedUnpaused(ToxFile file, bool paused); + void fileTransferBrokenUnbroken(ToxFile file, bool broken); protected: QString getHumanReadableSize(qint64 size); diff --git a/src/core/corefile.cpp b/src/core/corefile.cpp index 299df352a..4b5f355ea 100644 --- a/src/core/corefile.cpp +++ b/src/core/corefile.cpp @@ -34,6 +34,8 @@ void CoreFile::sendAvatarFile(Core* core, uint32_t friendId, const QByteArray& d file.fileName = QByteArray((char*)filename, TOX_HASH_LENGTH); file.fileKind = TOX_FILE_KIND_AVATAR; file.avatarData = data; + file.resumeFileId.resize(TOX_FILE_ID_LENGTH); + tox_file_get_file_id(core->tox, friendId, fileNum, (uint8_t*)file.resumeFileId.data(), nullptr); addFile(friendId, fileNum, file); } @@ -54,6 +56,8 @@ void CoreFile::sendFile(Core* core, uint32_t friendId, QString Filename, QString ToxFile file{fileNum, friendId, fileName, FilePath, ToxFile::SENDING}; file.filesize = filesize; + file.resumeFileId.resize(TOX_FILE_ID_LENGTH); + tox_file_get_file_id(core->tox, friendId, fileNum, (uint8_t*)file.resumeFileId.data(), nullptr); if (!file.open(false)) { qWarning() << QString("CoreFile::sendFile: Can't open file, error: %1").arg(file.file->errorString()); @@ -240,6 +244,8 @@ void CoreFile::onFileReceiveCallback(Tox*, uint32_t friendId, uint32_t fileId, u CString::toString(fname,fnameLen).toUtf8(), "", ToxFile::RECEIVING}; file.filesize = filesize; file.fileKind = kind; + file.resumeFileId.resize(TOX_FILE_ID_LENGTH); + tox_file_get_file_id(core->tox, friendId, fileId, (uint8_t*)file.resumeFileId.data(), nullptr); addFile(friendId, fileId, file); if (kind != TOX_FILE_KIND_AVATAR) emit core->fileReceiveRequested(file); @@ -392,6 +398,12 @@ void CoreFile::onFileRecvChunkCallback(Tox *tox, uint32_t friendId, uint32_t fil void CoreFile::onConnectionStatusChanged(Core* core, uint32_t friendId, bool online) { + /// TODO: Actually resume broken file transfers + /// We need to: + /// - Start a new file transfer with the same 32byte file ID with toxcore + /// - Seek to the correct position again + /// - Update the fileNum in our ToxFile + /// - Update the users of our signals to check the 32byte tox file ID, not the uint32_t file_num (fileId) ToxFile::FileStatus status = online ? ToxFile::TRANSMITTING : ToxFile::BROKEN; for (uint64_t key : fileMap.keys()) { diff --git a/src/core/corestructs.h b/src/core/corestructs.h index 388b94366..0edbfdc9c 100644 --- a/src/core/corestructs.h +++ b/src/core/corestructs.h @@ -80,6 +80,7 @@ struct ToxFile FileDirection direction; QTimer* sendTimer; QByteArray avatarData; + QByteArray resumeFileId; }; #endif // CORESTRUCTS_H From e682dada3bde95d01c143ac10f4179c6b10cf4ad Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 25 Apr 2015 20:20:53 +0200 Subject: [PATCH 45/51] Fix save corruption bug Don't just let the user close the profile select box and continue with an empty value. We would create a new profile and save it back on top of the previous encrypted profile --- src/core/core.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 7a458d6dc..834efb5cb 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -861,6 +861,8 @@ QByteArray Core::loadToxSave(QString path) tr("Your profile is already used by another qTox\n" "Please select another profile")); path = Settings::getInstance().askProfiles(); + if (path.isEmpty()) + continue; Settings::getInstance().switchProfile(QFileInfo(path).baseName()); HistoryKeeper::resetInstance(); } @@ -890,7 +892,10 @@ QByteArray Core::loadToxSave(QString path) { configurationFile.close(); - QString profile = Settings::getInstance().askProfiles(); + QString profile; + do { + profile = Settings::getInstance().askProfiles(); + } while (profile.isEmpty()); if (!profile.isEmpty()) { From 7eb9370c0b7b740cbd847bffb285dc1a614ad997 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 25 Apr 2015 21:05:29 +0200 Subject: [PATCH 46/51] Disable the GUI until a profile is active There are small instants on startup and while profile switching during which no profile is loaded but the GUI could still receive events, e.g. between two modal windows. Disable the GUI to prevent that. --- src/core/core.cpp | 5 +++-- src/nexus.cpp | 6 ++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 834efb5cb..a99da9ff8 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -327,6 +327,9 @@ void Core::start() emit idSet(getSelfId().toString()); } + if (isReady()) + GUI::setEnabled(true); + process(); // starts its own timer } @@ -988,8 +991,6 @@ void Core::switchConfiguration(const QString& _profile) HistoryKeeper::resetInstance(); start(); - if (isReady()) - GUI::setEnabled(true); } void Core::loadFriends() diff --git a/src/nexus.cpp b/src/nexus.cpp index 2473dcbb5..d716ed78a 100644 --- a/src/nexus.cpp +++ b/src/nexus.cpp @@ -79,6 +79,12 @@ void Nexus::start() #endif GUI::getInstance(); + // Zetok protection + // There are small instants on startup during which no + // profile is loaded but the GUI could still receive events, + // e.g. between two modal windows. Disable the GUI to prevent that. + GUI::setEnabled(false); + // Connections #ifdef Q_OS_ANDROID connect(core, &Core::connected, androidgui, &AndroidGUI::onConnected); From d962148dd07369655cdf5e6af48a551d0d432050 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sat, 25 Apr 2015 21:33:15 +0200 Subject: [PATCH 47/51] Fix more save corruption bugs askProfiles is a really dangerous function. Awful things happen when the user closes that message box. We now prevent it from being closed in more places --- src/core/core.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index a99da9ff8..733730250 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -863,10 +863,11 @@ QByteArray Core::loadToxSave(QString path) GUI::showWarning(tr("Profile already in use"), tr("Your profile is already used by another qTox\n" "Please select another profile")); - path = Settings::getInstance().askProfiles(); - if (path.isEmpty()) + QString tmppath = Settings::getInstance().askProfiles(); + if (tmppath.isEmpty()) continue; - Settings::getInstance().switchProfile(QFileInfo(path).baseName()); + Settings::getInstance().switchProfile(tmppath); + path = QDir(Settings::getSettingsDirPath()).filePath(tmppath + TOX_EXT); HistoryKeeper::resetInstance(); } @@ -875,7 +876,7 @@ QByteArray Core::loadToxSave(QString path) if (!configurationFile.exists()) { - qWarning() << "The Tox configuration file was not found"; + qWarning() << "The Tox configuration file "< Date: Sat, 25 Apr 2015 22:07:12 +0200 Subject: [PATCH 48/51] Better error messages for friend requests --- src/core/core.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 733730250..b1f24a67c 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -561,7 +561,15 @@ void Core::requestFriendship(const QString& friendAddress, const QString& messag { const QString userId = friendAddress.mid(0, TOX_PUBLIC_KEY_SIZE * 2); - if (hasFriendWithAddress(friendAddress)) + if (message.isEmpty()) + { + emit failedToAddFriend(userId, QString(tr("You need to write a message with you request"))); + } + else if (message.size() > TOX_MAX_FRIEND_REQUEST_LENGTH) + { + emit failedToAddFriend(userId, QString(tr("Your message is too long!"))); + } + else if (hasFriendWithAddress(friendAddress)) { emit failedToAddFriend(userId, QString(tr("Friend is already added"))); } From a31b33106ad8841250a0213d469af3fafc79b0ef Mon Sep 17 00:00:00 2001 From: agilob Date: Sat, 25 Apr 2015 21:48:44 +0100 Subject: [PATCH 49/51] added missing lib for ubuntu --- simple_make.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/simple_make.sh b/simple_make.sh index f43bd91fa..d58cd9606 100755 --- a/simple_make.sh +++ b/simple_make.sh @@ -2,7 +2,9 @@ if which apt-get; then sudo apt-get install build-essential qt5-qmake qt5-default libopenal-dev libopencv-dev \ - libtool autotools-dev automake checkinstall check libopus-dev libvpx-dev qttools5-dev-tools qtchooser libxss-dev libqt5svg5* libqrencode-dev + libtool autotools-dev automake checkinstall check libopus-dev libvpx-dev \ + qttools5-dev-tools qtchooser libxss-dev libqt5svg5* libqrencode-dev \ + libqt5opengl5-dev elif which pacman; then sudo pacman -S --needed base-devel qt5 opencv openal opus libvpx libxss qt5-svg qrencode elif which yum; then From 8786f9525ef4098f843381516483f84ab4571108 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sun, 26 Apr 2015 14:40:07 +0200 Subject: [PATCH 50/51] Fix #1536 New friends must be added to the friend list before loading history, otherwise the history code won't find the friend in the friendlist, and the history will have blank names for the friend --- src/friend.cpp | 14 +++++++++----- src/friend.h | 3 +++ src/friendlist.cpp | 4 ++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/friend.cpp b/src/friend.cpp index 82f66cb30..cfeb1266f 100644 --- a/src/friend.cpp +++ b/src/friend.cpp @@ -35,11 +35,6 @@ Friend::Friend(uint32_t FriendId, const ToxID &UserId) widget = new FriendWidget(friendId, getDisplayedName()); chatForm = new ChatForm(this); - if (Settings::getInstance().getEnableLogging()) - { - chatForm->loadHistory(QDateTime::currentDateTime().addDays(-7), true); - widget->historyLoaded = true; - } } Friend::~Friend() @@ -48,6 +43,15 @@ Friend::~Friend() delete widget; } +void Friend::loadHistory() +{ + if (Settings::getInstance().getEnableLogging()) + { + chatForm->loadHistory(QDateTime::currentDateTime().addDays(-7), true); + widget->historyLoaded = true; + } +} + void Friend::setName(QString name) { userName = name; diff --git a/src/friend.h b/src/friend.h index 8ffb19f5a..b0fa63fec 100644 --- a/src/friend.h +++ b/src/friend.h @@ -33,6 +33,9 @@ public: ~Friend(); Friend& operator=(const Friend& other)=delete; + /// Loads the friend's chat history if enabled + void loadHistory(); + void setName(QString name); void setAlias(QString name); QString getDisplayedName() const; diff --git a/src/friendlist.cpp b/src/friendlist.cpp index a783769c1..100d07169 100644 --- a/src/friendlist.cpp +++ b/src/friendlist.cpp @@ -34,6 +34,10 @@ Friend* FriendList::addFriend(int friendId, const ToxID& userId) friendList[friendId] = newfriend; tox2id[userId.publicKey] = friendId; + // Must be done AFTER adding to the friendlist + // or we won't find the friend and history will have blank names + newfriend->loadHistory(); + return newfriend; } From 542cae85d399b26c9490ac0385da5bb337e977b5 Mon Sep 17 00:00:00 2001 From: tux3 Date: Sun, 26 Apr 2015 17:39:39 +0200 Subject: [PATCH 51/51] Give appropriately scary name to dangerous function "isPathWritable" didn't convey really well the meaning of "let's try to open it, wipe everything the hell out, and see if it worked" --- src/chatlog/content/filetransferwidget.cpp | 4 ++-- src/nexus.cpp | 2 +- src/nexus.h | 2 +- src/widget/form/profileform.cpp | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/chatlog/content/filetransferwidget.cpp b/src/chatlog/content/filetransferwidget.cpp index 1888a229c..fe040bf23 100644 --- a/src/chatlog/content/filetransferwidget.cpp +++ b/src/chatlog/content/filetransferwidget.cpp @@ -118,7 +118,7 @@ void FileTransferWidget::autoAcceptTransfer(const QString &path) //Do not automatically accept the file-transfer if the path is not writable. //The user can still accept it manually. - if (Nexus::isFilePathWritable(filepath)) + if (Nexus::tryRemoveFile(filepath)) Core::getInstance()->acceptFileRecvRequest(fileInfo.friendId, fileInfo.fileNum, filepath); else qDebug() << "Warning: Cannot write to " << filepath; @@ -130,7 +130,7 @@ void FileTransferWidget::acceptTransfer(const QString &filepath) return; //test if writable - if(!Nexus::isFilePathWritable(filepath)) + if(!Nexus::tryRemoveFile(filepath)) { QMessageBox::warning(0, tr("Location not writable","Title of permissions popup"), diff --git a/src/nexus.cpp b/src/nexus.cpp index d716ed78a..a1502dce4 100644 --- a/src/nexus.cpp +++ b/src/nexus.cpp @@ -180,7 +180,7 @@ QString Nexus::getSupportedImageFilter() return tr("Images (%1)", "filetype filter").arg(res.left(res.size()-1)); } -bool Nexus::isFilePathWritable(const QString& filepath) +bool Nexus::tryRemoveFile(const QString& filepath) { QFile tmp(filepath); bool writable = tmp.open(QIODevice::WriteOnly); diff --git a/src/nexus.h b/src/nexus.h index 05c0e8ff3..a411b1f22 100644 --- a/src/nexus.h +++ b/src/nexus.h @@ -23,7 +23,7 @@ public: static AndroidGUI* getAndroidGUI(); ///< Will return 0 if not started static Widget* getDesktopGUI(); ///< Will return 0 if not started static QString getSupportedImageFilter(); - static bool isFilePathWritable(const QString& filepath); // WARNING: Tests by brute force, i.e. removes the file in question + static bool tryRemoveFile(const QString& filepath); ///< Dangerous way to find out if a path is writable private: explicit Nexus(QObject *parent = 0); diff --git a/src/widget/form/profileform.cpp b/src/widget/form/profileform.cpp index 938e98799..66561035d 100644 --- a/src/widget/form/profileform.cpp +++ b/src/widget/form/profileform.cpp @@ -278,7 +278,7 @@ void ProfileForm::onExportClicked() tr("Tox save file (*.tox)", "save dialog filter")); if (!path.isEmpty()) { - if (!Nexus::isFilePathWritable(path)) + if (!Nexus::tryRemoveFile(path)) { GUI::showWarning(tr("Location not writable","Title of permissions popup"), tr("You do not have permission to write that location. Choose another, or cancel the save dialog.", "text of permissions popup")); return; @@ -386,7 +386,7 @@ void ProfileForm::on_saveQr_clicked() tr("Save QrCode (*.png)", "save dialog filter")); if (!path.isEmpty()) { - if (!Nexus::isFilePathWritable(path)) + if (!Nexus::tryRemoveFile(path)) { GUI::showWarning(tr("Location not writable","Title of permissions popup"), tr("You do not have permission to write that location. Choose another, or cancel the save dialog.", "text of permissions popup")); return;