mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Implement file reception, improve sending
This commit is contained in:
parent
b6b062d8b9
commit
782bce2c05
41
chatform.cpp
41
chatform.cpp
@ -41,11 +41,13 @@ ChatForm::ChatForm(Friend* chatFriend)
|
||||
sendButton->setPalette(toxgreen);
|
||||
sendButton->setAutoFillBackground(true);
|
||||
sendButton->setFixedSize(50, 50);
|
||||
sendButton->setIconSize(QSize(25,25));
|
||||
fileButton->setIcon(QIcon("img/button icons/attach_2x.png"));
|
||||
fileButton->setFlat(true);
|
||||
fileButton->setPalette(toxgreen);
|
||||
fileButton->setAutoFillBackground(true);
|
||||
fileButton->setIconSize(QSize(40,40));
|
||||
fileButton->setIconSize(QSize(20,20));
|
||||
fileButton->setFixedSize(50,40);
|
||||
|
||||
main->setLayout(mainLayout);
|
||||
mainLayout->addWidget(chatArea);
|
||||
@ -178,9 +180,9 @@ void ChatForm::onSliderRangeChanged()
|
||||
scroll->setValue(scroll->maximum());
|
||||
}
|
||||
|
||||
void ChatForm::startFileSend(ToxFile *file)
|
||||
void ChatForm::startFileSend(ToxFile file)
|
||||
{
|
||||
if (file->friendId != f->friendId)
|
||||
if (file.friendId != f->friendId)
|
||||
return;
|
||||
QLabel *author = new QLabel(Widget::getInstance()->getUsername());
|
||||
QLabel *date = new QLabel(QTime::currentTime().toString("mm:ss"));
|
||||
@ -213,3 +215,36 @@ void ChatForm::startFileSend(ToxFile *file)
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferCancelled, fileTrans, &FileTransfertWidget::onFileTransferCancelled);
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferFinished, fileTrans, &FileTransfertWidget::onFileTransferFinished);
|
||||
}
|
||||
|
||||
void ChatForm::onFileRecvRequest(ToxFile file)
|
||||
{
|
||||
if (file.friendId != f->friendId)
|
||||
return;
|
||||
QLabel *author = new QLabel(f->getName());
|
||||
QLabel *date = new QLabel(QTime::currentTime().toString("mm:ss"));
|
||||
QScrollBar* scroll = chatArea->verticalScrollBar();
|
||||
lockSliderToBottom = scroll && scroll->value() == scroll->maximum();
|
||||
author->setAlignment(Qt::AlignTop | Qt::AlignRight);
|
||||
date->setAlignment(Qt::AlignTop);
|
||||
if (previousName.isEmpty() || previousName != author->text())
|
||||
{
|
||||
if (curRow)
|
||||
{
|
||||
mainChatLayout->setRowStretch(curRow, 0);
|
||||
mainChatLayout->addItem(new QSpacerItem(0,AUTHOR_CHANGE_SPACING),curRow,0,1,3);
|
||||
curRow++;
|
||||
}
|
||||
mainChatLayout->addWidget(author, curRow, 0);
|
||||
}
|
||||
FileTransfertWidget* fileTrans = new FileTransfertWidget(file);
|
||||
previousName = author->text();
|
||||
mainChatLayout->addWidget(fileTrans, curRow, 1);
|
||||
mainChatLayout->addWidget(date, curRow, 3);
|
||||
mainChatLayout->setRowStretch(curRow+1, 1);
|
||||
mainChatLayout->setRowStretch(curRow, 0);
|
||||
curRow++;
|
||||
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferInfo, fileTrans, &FileTransfertWidget::onFileTransferInfo);
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferCancelled, fileTrans, &FileTransfertWidget::onFileTransferCancelled);
|
||||
connect(Widget::getInstance()->getCore(), &Core::fileTransferFinished, fileTrans, &FileTransfertWidget::onFileTransferFinished);
|
||||
}
|
||||
|
@ -37,7 +37,8 @@ signals:
|
||||
void sendFile(int32_t, QString, QByteArray);
|
||||
|
||||
public slots:
|
||||
void startFileSend(ToxFile* file);
|
||||
void startFileSend(ToxFile file);
|
||||
void onFileRecvRequest(ToxFile file);
|
||||
|
||||
private slots:
|
||||
void onSendTriggered();
|
||||
|
423
core.cpp
423
core.cpp
@ -23,11 +23,18 @@
|
||||
#include <QStandardPaths>
|
||||
#include <QtEndian>
|
||||
#include <QThread>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#define GROUPCHAT_MAX_SIZE 32
|
||||
#define TOX_SAVE_INTERVAL 30*1000
|
||||
#define TOX_FILE_INTERVAL 20
|
||||
#define TOX_BOOTSTRAP_INTERVAL 10*1000
|
||||
|
||||
const QString Core::CONFIG_FILE_NAME = "tox_save";
|
||||
QList<ToxFile> Core::fileSendQueue;
|
||||
QList<ToxFile> Core::fileRecvQueue;
|
||||
|
||||
Core::Core() :
|
||||
tox(nullptr)
|
||||
@ -36,13 +43,13 @@ Core::Core() :
|
||||
toxTimer->setSingleShot(true);
|
||||
saveTimer = new QTimer(this);
|
||||
saveTimer->start(TOX_SAVE_INTERVAL);
|
||||
fileTimer = new QTimer(this);
|
||||
fileTimer->start(TOX_FILE_INTERVAL);
|
||||
//fileTimer = new QTimer(this);
|
||||
//fileTimer->start(TOX_FILE_INTERVAL);
|
||||
bootstrapTimer = new QTimer(this);
|
||||
bootstrapTimer->start(TOX_BOOTSTRAP_INTERVAL);
|
||||
connect(toxTimer, &QTimer::timeout, this, &Core::process);
|
||||
connect(saveTimer, &QTimer::timeout, this, &Core::saveConfiguration);
|
||||
connect(fileTimer, &QTimer::timeout, this, &Core::fileHeartbeat);
|
||||
//connect(fileTimer, &QTimer::timeout, this, &Core::fileHeartbeat);
|
||||
connect(bootstrapTimer, &QTimer::timeout, this, &Core::onBootstrapTimer);
|
||||
connect(&Settings::getInstance(), &Settings::dhtServerListChanged, this, &Core::bootstrapDht);
|
||||
}
|
||||
@ -137,71 +144,77 @@ void Core::onGroupNamelistChange(Tox*, int groupnumber, int peernumber, uint8_t
|
||||
emit static_cast<Core*>(core)->groupNamelistChanged(groupnumber, peernumber, change);
|
||||
}
|
||||
|
||||
void Core::onFileSendRequestCallback(Tox* tox, int32_t friendnumber, uint8_t filenumber, uint64_t filesize,
|
||||
uint8_t *filename, uint16_t filename_length, void *userdata)
|
||||
void Core::onFileSendRequestCallback(Tox*, int32_t friendnumber, uint8_t filenumber, uint64_t filesize,
|
||||
uint8_t *filename, uint16_t filename_length, void *core)
|
||||
{
|
||||
qDebug() << "Core: File send request callback";
|
||||
qDebug() << QString("Core: Received file request %1 with friend %2").arg(filenumber).arg(friendnumber);
|
||||
|
||||
fileRecvQueue.append(ToxFile(filenumber, friendnumber, QByteArray(), filesize,
|
||||
CString::toString(filename,filename_length).toUtf8(), ToxFile::RECEIVING));
|
||||
emit static_cast<Core*>(core)->fileReceiveRequested(fileRecvQueue.last());
|
||||
}
|
||||
void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber,
|
||||
uint8_t control_type, uint8_t *data, uint16_t length, void *core)
|
||||
void Core::onFileControlCallback(Tox*, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber,
|
||||
uint8_t control_type, uint8_t*, uint16_t, void *core)
|
||||
{
|
||||
ToxFile* file{nullptr};
|
||||
if (receive_send == 1)
|
||||
{
|
||||
for (ToxFile& f : fileSendQueue)
|
||||
{
|
||||
if (f.fileNum == filenumber)
|
||||
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");
|
||||
// TODO: Warn the Friend* that we're aborting (emit)
|
||||
return;
|
||||
}
|
||||
if (control_type == TOX_FILECONTROL_ACCEPT && receive_send == 1)
|
||||
{
|
||||
emit static_cast<Core*>(core)->fileTransferAccepted(file);
|
||||
qDebug() << "Core: File control callback, file accepted";
|
||||
int chunkSize = tox_file_data_size(tox, friendnumber);
|
||||
if (chunkSize == -1)
|
||||
{
|
||||
qWarning("Core::onFileControlCallback: Error getting preffered chunk size, aborting file send");
|
||||
file->status = ToxFile::STOPPED;
|
||||
emit static_cast<Core*>(core)->fileTransferCancelled(file);
|
||||
tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0);
|
||||
return;
|
||||
}
|
||||
chunkSize = std::min(chunkSize, file->fileData.size());
|
||||
QByteArray toSend = file->fileData.mid(file->bytesSent, chunkSize);
|
||||
if (tox_file_send_data(tox, friendnumber, filenumber, (uint8_t*)toSend.data(), toSend.size()) == -1)
|
||||
{
|
||||
qWarning("Core::onFileControlCallback: Error sending first data chunk, aborting");
|
||||
file->status = ToxFile::STOPPED;
|
||||
emit static_cast<Core*>(core)->fileTransferCancelled(file);
|
||||
tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
file->bytesSent += chunkSize;
|
||||
if (file->bytesSent >= file->fileData.size())
|
||||
{
|
||||
qWarning("Core::onFileControlCallback: Transfer finished");
|
||||
tox_file_send_control(tox, friendnumber, 0, filenumber, TOX_FILECONTROL_FINISHED, nullptr, 0);
|
||||
emit static_cast<Core*>(core)->fileTransferFinished(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
file->status = ToxFile::TRANSMITTING;
|
||||
}
|
||||
}
|
||||
emit static_cast<Core*>(core)->fileTransferAccepted(*file);
|
||||
qDebug() << "Core: File control callback, file accepted";
|
||||
file->sendFuture = QtConcurrent::run(sendAllFileData, static_cast<Core*>(core), file);
|
||||
}
|
||||
else if (receive_send == 1 && control_type == TOX_FILECONTROL_KILL)
|
||||
{
|
||||
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*>(core)->fileTransferCancelled(file);
|
||||
emit static_cast<Core*>(core)->fileTransferCancelled(file->friendId, file->fileNum, ToxFile::SENDING);
|
||||
file->sendFuture.waitForFinished(); // Wait for sendAllFileData to return before deleting the ToxFile
|
||||
removeFileFromQueue(true, file->friendId, file->fileNum);
|
||||
}
|
||||
else if (receive_send == 0 && control_type == TOX_FILECONTROL_KILL)
|
||||
{
|
||||
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*>(core)->fileTransferCancelled(file->friendId, file->fileNum, ToxFile::RECEIVING);
|
||||
removeFileFromQueue(false, file->friendId, file->fileNum);
|
||||
}
|
||||
else if (receive_send == 0 && control_type == TOX_FILECONTROL_FINISHED)
|
||||
{
|
||||
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*>(core)->fileTransferFinished(*file);
|
||||
removeFileFromQueue(false, file->friendId, file->fileNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -210,9 +223,28 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive
|
||||
}
|
||||
}
|
||||
|
||||
void Core::onFileDataCallback(Tox* tox, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata)
|
||||
void Core::onFileDataCallback(Tox*, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *core)
|
||||
{
|
||||
qDebug() << "Core: File data callback";
|
||||
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->fileData.append((char*)data,length);
|
||||
file->bytesSent += length;
|
||||
//qDebug() << QString("Core::onFileDataCallback: received %1/%2 bytes").arg(file->fileData.size()).arg(file->filesize);
|
||||
emit static_cast<Core*>(core)->fileTransferInfo(file->friendId, file->fileNum,
|
||||
file->filesize, file->bytesSent, ToxFile::RECEIVING);
|
||||
}
|
||||
|
||||
void Core::acceptFriendRequest(const QString& userId)
|
||||
@ -227,11 +259,11 @@ void Core::acceptFriendRequest(const QString& userId)
|
||||
|
||||
void Core::requestFriendship(const QString& friendAddress, const QString& message)
|
||||
{
|
||||
qDebug() << "Core: requesting friendship of "+friendAddress;
|
||||
CString cMessage(message);
|
||||
|
||||
int friendId = tox_add_friend(tox, CFriendAddress(friendAddress).data(), cMessage.data(), cMessage.size());
|
||||
const QString userId = friendAddress.mid(0, TOX_CLIENT_ID_SIZE * 2);
|
||||
// TODO: better error handling
|
||||
if (friendId < 0) {
|
||||
emit failedToAddFriend(userId);
|
||||
} else {
|
||||
@ -277,17 +309,163 @@ void Core::sendFile(int32_t friendId, QString Filename, QByteArray data)
|
||||
qWarning() << "Core::sendFile: Can't create the Tox file sender";
|
||||
return;
|
||||
}
|
||||
qDebug() << QString("Core::sendFile: Created file sender %1 with friend %2").arg(fileNum).arg(friendId);
|
||||
|
||||
fileSendQueue.append(ToxFile(fileNum, friendId, data, fileName, ToxFile::SENDING));
|
||||
fileSendQueue.append(ToxFile(fileNum, friendId, data, data.size(), fileName, ToxFile::SENDING));
|
||||
|
||||
emit fileSendStarted(&fileSendQueue.last());
|
||||
emit fileSendStarted(fileSendQueue.last());
|
||||
}
|
||||
|
||||
void Core::cancelFileSend(ToxFile* file)
|
||||
void Core::pauseResumeFileSend(int friendId, int 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;
|
||||
}
|
||||
if (file->status == ToxFile::TRANSMITTING)
|
||||
{
|
||||
file->status = ToxFile::PAUSED;
|
||||
emit fileTransferPaused(file->friendId, file->fileNum, ToxFile::SENDING);
|
||||
tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_PAUSE, nullptr, 0);
|
||||
}
|
||||
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);
|
||||
}
|
||||
else
|
||||
qWarning() << "Core::pauseResumeFileSend: File is stopped";
|
||||
}
|
||||
|
||||
void Core::pauseResumeFileRecv(int friendId, int 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->friendId, file->fileNum, ToxFile::RECEIVING);
|
||||
tox_file_send_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_PAUSE, nullptr, 0);
|
||||
}
|
||||
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);
|
||||
}
|
||||
else
|
||||
qWarning() << "Core::pauseResumeFileRecv: File is stopped";
|
||||
}
|
||||
|
||||
void Core::cancelFileSend(int friendId, int 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);
|
||||
emit fileTransferCancelled(file->friendId, file->fileNum, ToxFile::SENDING);
|
||||
tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0);
|
||||
file->sendFuture.waitForFinished(); // Wait until sendAllFileData returns before deleting
|
||||
removeFileFromQueue(true, friendId, fileNum);
|
||||
}
|
||||
|
||||
void Core::cancelFileRecv(int friendId, int 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->friendId, file->fileNum, ToxFile::RECEIVING);
|
||||
tox_file_send_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0);
|
||||
removeFileFromQueue(true, friendId, fileNum);
|
||||
}
|
||||
|
||||
void Core::rejectFileRecvRequest(int friendId, int 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->friendId, file->fileNum, ToxFile::SENDING);
|
||||
tox_file_send_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0);
|
||||
removeFileFromQueue(false, friendId, fileNum);
|
||||
}
|
||||
|
||||
void Core::acceptFileRecvRequest(int friendId, int fileNum)
|
||||
{
|
||||
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->status = ToxFile::TRANSMITTING;
|
||||
emit fileTransferAccepted(*file);
|
||||
tox_file_send_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_ACCEPT, nullptr, 0);
|
||||
}
|
||||
|
||||
void Core::removeFriend(int friendId)
|
||||
@ -360,7 +538,7 @@ void Core::bootstrapDht()
|
||||
static int j = 0;
|
||||
int i=0;
|
||||
int listSize = dhtServerList.size();
|
||||
while (i<2)
|
||||
while (i<5)
|
||||
{
|
||||
const Settings::DhtServer& dhtServer = dhtServerList[j % listSize];
|
||||
if (tox_bootstrap_from_address(tox, dhtServer.address.toLatin1().data(),
|
||||
@ -386,46 +564,6 @@ void Core::process()
|
||||
toxTimer->start(tox_do_interval(tox));
|
||||
}
|
||||
|
||||
void Core::fileHeartbeat()
|
||||
{
|
||||
for (ToxFile& file : fileSendQueue)
|
||||
{
|
||||
if (file.status == ToxFile::TRANSMITTING)
|
||||
{
|
||||
emit fileTransferInfo(&file);
|
||||
int chunkSize = tox_file_data_size(tox, file.friendId);
|
||||
if (chunkSize == -1)
|
||||
{
|
||||
qWarning("Core::fileHeartbeat: Error getting preffered chunk size, aborting file send");
|
||||
file.status = ToxFile::STOPPED;
|
||||
emit fileTransferCancelled(&file);
|
||||
tox_file_send_control(tox, file.friendId, 0, file.fileNum, TOX_FILECONTROL_KILL, nullptr, 0);
|
||||
return;
|
||||
}
|
||||
chunkSize = std::min(chunkSize, file.fileData.size());
|
||||
QByteArray toSend = file.fileData.mid(file.bytesSent, chunkSize);
|
||||
if (tox_file_send_data(tox, file.friendId, file.fileNum, (uint8_t*)toSend.data(), toSend.size()) == -1)
|
||||
{
|
||||
qWarning("Core::fileHeartbeat: Error sending data chunk");
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
file.bytesSent += chunkSize;
|
||||
if (file.bytesSent >= file.fileData.size())
|
||||
{
|
||||
qDebug("Core::fileHeartbeat: Transfer finished");
|
||||
tox_file_send_control(tox, file.friendId, 0, file.fileNum, TOX_FILECONTROL_FINISHED, nullptr, 0);
|
||||
file.status = ToxFile::STOPPED; // TODO: Remove it from the list and return;
|
||||
emit fileTransferFinished(&file);
|
||||
}
|
||||
else
|
||||
qDebug() << QString("Core::fileHeartbeat: sent %1/%2 bytes").arg(file.bytesSent).arg(file.fileData.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Core::checkConnection()
|
||||
{
|
||||
static bool isConnected = false;
|
||||
@ -553,17 +691,6 @@ void Core::start()
|
||||
|
||||
loadConfiguration();
|
||||
|
||||
uint8_t friendAddress[TOX_FRIEND_ADDRESS_SIZE];
|
||||
tox_get_address(tox, friendAddress);
|
||||
|
||||
emit friendAddressGenerated(CFriendAddress::toString(friendAddress));
|
||||
|
||||
CString cUsername(Settings::getInstance().getUsername());
|
||||
tox_set_name(tox, cUsername.data(), cUsername.size());
|
||||
|
||||
CString cStatusMessage(Settings::getInstance().getStatusMessage());
|
||||
tox_set_status_message(tox, cStatusMessage.data(), cStatusMessage.size());
|
||||
|
||||
tox_callback_friend_request(tox, onFriendRequest, this);
|
||||
tox_callback_friend_message(tox, onFriendMessage, this);
|
||||
tox_callback_friend_action(tox, onAction, this);
|
||||
@ -579,6 +706,17 @@ void Core::start()
|
||||
tox_callback_file_control(tox, onFileControlCallback, this);
|
||||
tox_callback_file_data(tox, onFileDataCallback, this);
|
||||
|
||||
uint8_t friendAddress[TOX_FRIEND_ADDRESS_SIZE];
|
||||
tox_get_address(tox, friendAddress);
|
||||
|
||||
emit friendAddressGenerated(CFriendAddress::toString(friendAddress));
|
||||
|
||||
CString cUsername(Settings::getInstance().getUsername());
|
||||
tox_set_name(tox, cUsername.data(), cUsername.size());
|
||||
|
||||
CString cStatusMessage(Settings::getInstance().getStatusMessage());
|
||||
tox_set_status_message(tox, cStatusMessage.data(), cStatusMessage.size());
|
||||
|
||||
bootstrapDht();
|
||||
|
||||
toxTimer->start(tox_do_interval(tox));
|
||||
@ -733,3 +871,80 @@ void Core::quitGroupChat(int groupId) const
|
||||
{
|
||||
tox_del_groupchat(tox, groupId);
|
||||
}
|
||||
|
||||
void Core::removeFileFromQueue(bool sendQueue, int friendId, int fileId)
|
||||
{
|
||||
bool found = false;
|
||||
if (sendQueue)
|
||||
{
|
||||
for (int i=0; i<fileSendQueue.size();)
|
||||
{
|
||||
if (fileSendQueue[i].friendId == friendId && fileSendQueue[i].fileNum == fileId)
|
||||
{
|
||||
found = true;
|
||||
fileSendQueue.removeAt(i);
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i=0; i<fileRecvQueue.size();)
|
||||
{
|
||||
if (fileRecvQueue[i].friendId == friendId && fileRecvQueue[i].fileNum == fileId)
|
||||
{
|
||||
found = true;
|
||||
fileRecvQueue.removeAt(i);
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
qWarning() << "Core::removeFileFromQueue: No such file in queue";
|
||||
}
|
||||
|
||||
void Core::sendAllFileData(Core *core, ToxFile* file)
|
||||
{
|
||||
while (file->bytesSent < file->fileData.size())
|
||||
{
|
||||
if (file->status == ToxFile::PAUSED)
|
||||
{
|
||||
QThread::sleep(0);
|
||||
continue;
|
||||
}
|
||||
else if (file->status == ToxFile::STOPPED)
|
||||
{
|
||||
qWarning("Core::sendAllFileData: File is stopped");
|
||||
return;
|
||||
}
|
||||
emit core->fileTransferInfo(file->friendId, file->fileNum, file->filesize, file->bytesSent, ToxFile::SENDING);
|
||||
qApp->processEvents();
|
||||
int 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->friendId, file->fileNum, ToxFile::SENDING);
|
||||
tox_file_send_control(core->tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0);
|
||||
removeFileFromQueue(true, file->friendId, file->fileNum);
|
||||
return;
|
||||
}
|
||||
chunkSize = std::min(chunkSize, file->fileData.size());
|
||||
QByteArray toSend = file->fileData.mid(file->bytesSent, chunkSize);
|
||||
if (tox_file_send_data(core->tox, file->friendId, file->fileNum, (uint8_t*)toSend.data(), toSend.size()) == -1)
|
||||
{
|
||||
qWarning("Core::fileHeartbeat: Error sending data chunk");
|
||||
QThread::sleep(0);
|
||||
continue;
|
||||
}
|
||||
file->bytesSent += chunkSize;
|
||||
//qDebug() << QString("Core::fileHeartbeat: sent %1/%2 bytes").arg(file->bytesSent).arg(file->fileData.size());
|
||||
}
|
||||
qDebug("Core::fileHeartbeat: Transfer finished");
|
||||
tox_file_send_control(core->tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_FINISHED, nullptr, 0);
|
||||
file->status = ToxFile::STOPPED;
|
||||
emit core->fileTransferFinished(*file);
|
||||
removeFileFromQueue(true, file->friendId, file->fileNum);
|
||||
}
|
||||
|
41
core.h
41
core.h
@ -28,11 +28,7 @@
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QByteArray>
|
||||
|
||||
#define GROUPCHAT_MAX_SIZE 32
|
||||
#define TOX_SAVE_INTERVAL 30*1000
|
||||
#define TOX_FILE_INTERVAL 50
|
||||
#define TOX_BOOTSTRAP_INTERVAL 10*1000
|
||||
#include <QFuture>
|
||||
|
||||
struct DhtServer
|
||||
{
|
||||
@ -57,17 +53,20 @@ struct ToxFile
|
||||
RECEIVING
|
||||
};
|
||||
|
||||
ToxFile(int FileNum, int FriendId, QByteArray FileData, QByteArray FileName, FileDirection Direction)
|
||||
: fileNum(FileNum), friendId(FriendId), fileData{FileData},
|
||||
fileName{FileName}, bytesSent{0}, status{STOPPED}, direction{Direction} {}
|
||||
ToxFile()=default;
|
||||
ToxFile(int FileNum, int FriendId, QByteArray FileData, long long Filesize, QByteArray FileName, FileDirection Direction)
|
||||
: fileNum(FileNum), friendId(FriendId), fileData{FileData}, fileName{FileName},
|
||||
bytesSent{0}, filesize(Filesize), status{STOPPED}, direction{Direction} {}
|
||||
|
||||
int fileNum;
|
||||
int friendId;
|
||||
QByteArray fileData;
|
||||
QByteArray fileName;
|
||||
long long bytesSent;
|
||||
long long filesize;
|
||||
FileStatus status;
|
||||
FileDirection direction;
|
||||
QFuture<void> sendFuture;
|
||||
};
|
||||
|
||||
class Core : public QObject
|
||||
@ -101,6 +100,9 @@ private:
|
||||
void loadConfiguration();
|
||||
void saveConfiguration();
|
||||
void loadFriends();
|
||||
static void sendAllFileData(Core* core, ToxFile* file);
|
||||
|
||||
static void removeFileFromQueue(bool sendQueue, int friendId, int fileId);
|
||||
|
||||
void checkLastOnline(int friendId);
|
||||
|
||||
@ -108,7 +110,7 @@ private:
|
||||
QTimer *toxTimer, *saveTimer, *fileTimer, *bootstrapTimer;
|
||||
QList<DhtServer> dhtServerList;
|
||||
int dhtServerId;
|
||||
static QList<ToxFile> fileSendQueue;
|
||||
static QList<ToxFile> fileSendQueue, fileRecvQueue;
|
||||
|
||||
static const QString CONFIG_FILE_NAME;
|
||||
|
||||
@ -197,14 +199,18 @@ public slots:
|
||||
void sendTyping(int friendId, bool typing);
|
||||
|
||||
void sendFile(int32_t friendId, QString Filename, QByteArray data);
|
||||
void cancelFileSend(ToxFile* file);
|
||||
void cancelFileSend(int friendId, int fileNum);
|
||||
void cancelFileRecv(int friendId, int fileNum);
|
||||
void rejectFileRecvRequest(int friendId, int fileNum);
|
||||
void acceptFileRecvRequest(int friendId, int fileNum);
|
||||
void pauseResumeFileSend(int friendId, int fileNum);
|
||||
void pauseResumeFileRecv(int friendId, int fileNum);
|
||||
|
||||
void setUsername(const QString& username);
|
||||
void setStatusMessage(const QString& message);
|
||||
void setStatus(Status status);
|
||||
|
||||
void process();
|
||||
void fileHeartbeat();
|
||||
|
||||
void bootstrapDht();
|
||||
|
||||
@ -253,12 +259,13 @@ signals:
|
||||
|
||||
void failedToStart();
|
||||
|
||||
void fileSendStarted(ToxFile* file);
|
||||
void fileTransferAccepted(ToxFile* file);
|
||||
void fileTransferCancelled(ToxFile* file);
|
||||
void fileTransferFinished(ToxFile* file);
|
||||
void fileTransferPaused(ToxFile* file);
|
||||
void fileTransferInfo(ToxFile* file);
|
||||
void fileSendStarted(ToxFile file);
|
||||
void fileReceiveRequested(ToxFile file);
|
||||
void fileTransferAccepted(ToxFile file);
|
||||
void fileTransferCancelled(int FriendId, int FileNum, ToxFile::FileDirection direction);
|
||||
void fileTransferFinished(ToxFile file);
|
||||
void fileTransferPaused(int FriendId, int FileNum, ToxFile::FileDirection direction);
|
||||
void fileTransferInfo(int FriendId, int FileNum, int Filesize, int BytesSent, ToxFile::FileDirection direction);
|
||||
};
|
||||
|
||||
#endif // CORE_HPP
|
||||
|
@ -1,9 +1,12 @@
|
||||
#include "filetransfertwidget.h"
|
||||
#include "widget.h"
|
||||
#include "core.h"
|
||||
#include <QFileDialog>
|
||||
#include <QPixmap>
|
||||
|
||||
FileTransfertWidget::FileTransfertWidget(ToxFile *File)
|
||||
: file{File}, lastUpdate{QDateTime::currentDateTime()}, lastBytesSent{0}
|
||||
FileTransfertWidget::FileTransfertWidget(ToxFile File)
|
||||
: lastUpdate{QDateTime::currentDateTime()}, lastBytesSent{0},
|
||||
fileNum{File.fileNum}, friendId{File.friendId}, direction{File.direction}
|
||||
{
|
||||
pic=new QLabel(), filename=new QLabel(), size=new QLabel(), speed=new QLabel(), eta=new QLabel();
|
||||
topright = new QPushButton(), bottomright = new QPushButton();
|
||||
@ -18,13 +21,15 @@ FileTransfertWidget::FileTransfertWidget(ToxFile *File)
|
||||
setPalette(greybg);
|
||||
setAutoFillBackground(true);
|
||||
|
||||
setFixedSize(250,50);
|
||||
setMinimumSize(250,50);
|
||||
setLayout(mainLayout);
|
||||
mainLayout->setMargin(0);
|
||||
|
||||
filename->setText(file->fileName);
|
||||
pic->setMaximumHeight(40);
|
||||
pic->setContentsMargins(5,0,0,0);
|
||||
filename->setText(File.fileName);
|
||||
filename->setFont(prettysmall);
|
||||
size->setText(getHumanReadableSize(file->fileData.size()));
|
||||
size->setText(getHumanReadableSize(File.filesize));
|
||||
size->setFont(prettysmall);
|
||||
speed->setText("0B/s");
|
||||
speed->setFont(prettysmall);
|
||||
@ -35,11 +40,25 @@ FileTransfertWidget::FileTransfertWidget(ToxFile *File)
|
||||
progress->setFont(prettysmall);
|
||||
|
||||
topright->setIcon(QIcon("img/button icons/no_2x.png"));
|
||||
connect(topright, SIGNAL(clicked()), this, SLOT(cancelTransfer()));
|
||||
if (file->direction == ToxFile::SENDING)
|
||||
if (File.direction == ToxFile::SENDING)
|
||||
{
|
||||
bottomright->setIcon(QIcon("img/button icons/pause_2x.png"));
|
||||
connect(topright, SIGNAL(clicked()), this, SLOT(cancelTransfer()));
|
||||
connect(bottomright, SIGNAL(clicked()), this, SLOT(pauseResumeSend()));
|
||||
|
||||
QPixmap preview;
|
||||
if (preview.loadFromData(File.fileData))
|
||||
{
|
||||
preview = preview.scaledToHeight(40);
|
||||
pic->setPixmap(preview);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bottomright->setIcon(QIcon("img/button icons/yes_2x.png"));
|
||||
connect(topright, SIGNAL(clicked()), this, SLOT(rejectRecvRequest()));
|
||||
connect(bottomright, SIGNAL(clicked()), this, SLOT(acceptRecvRequest()));
|
||||
}
|
||||
|
||||
QPalette toxgreen;
|
||||
toxgreen.setColor(QPalette::Button, QColor(107,194,96)); // Tox Green
|
||||
@ -77,41 +96,47 @@ FileTransfertWidget::FileTransfertWidget(ToxFile *File)
|
||||
|
||||
QString FileTransfertWidget::getHumanReadableSize(int size)
|
||||
{
|
||||
static const char* suffix[] = {"B","kB","MB","GB","TB"};
|
||||
static const char* suffix[] = {"B","kiB","MiB","GiB","TiB"};
|
||||
int exp = 0;
|
||||
if (size)
|
||||
exp = std::min( (int) (log(size) / log(1000)), (int) (sizeof(suffix) / sizeof(suffix[0]) - 1));
|
||||
return QString().setNum(size / pow(1000, exp),'g',3).append(suffix[exp]);
|
||||
exp = std::min( (int) (log(size) / log(1024)), (int) (sizeof(suffix) / sizeof(suffix[0]) - 1));
|
||||
return QString().setNum(size / pow(1024, exp),'g',3).append(suffix[exp]);
|
||||
}
|
||||
|
||||
void FileTransfertWidget::onFileTransferInfo(ToxFile* File)
|
||||
void FileTransfertWidget::onFileTransferInfo(int FriendId, int FileNum, int Filesize, int BytesSent, ToxFile::FileDirection Direction)
|
||||
{
|
||||
if (File != file)
|
||||
if (FileNum != fileNum || FriendId != friendId || Direction != direction)
|
||||
return;
|
||||
QDateTime newtime = QDateTime::currentDateTime();
|
||||
int timediff = lastUpdate.secsTo(newtime);
|
||||
if (!timediff)
|
||||
if (timediff <= 0)
|
||||
return;
|
||||
int diff = File->bytesSent - lastBytesSent;
|
||||
int diff = BytesSent - lastBytesSent;
|
||||
if (diff < 0)
|
||||
diff = 0;
|
||||
int rawspeed = diff / timediff;
|
||||
speed->setText(getHumanReadableSize(rawspeed)+"/s");
|
||||
size->setText(getHumanReadableSize(File->fileData.size()));
|
||||
size->setText(getHumanReadableSize(Filesize));
|
||||
if (!rawspeed)
|
||||
return;
|
||||
int etaSecs = (File->fileData.size() - File->bytesSent) / rawspeed;
|
||||
int etaSecs = (Filesize - BytesSent) / rawspeed;
|
||||
QTime etaTime(0,0);
|
||||
etaTime = etaTime.addSecs(etaSecs);
|
||||
eta->setText(etaTime.toString("mm:ss"));
|
||||
progress->setValue(File->bytesSent*100/File->fileData.size());
|
||||
if (!Filesize)
|
||||
progress->setValue(0);
|
||||
else
|
||||
progress->setValue(BytesSent*100/Filesize);
|
||||
lastUpdate = newtime;
|
||||
lastBytesSent = File->bytesSent;
|
||||
lastBytesSent = BytesSent;
|
||||
}
|
||||
|
||||
void FileTransfertWidget::onFileTransferCancelled(ToxFile* File)
|
||||
void FileTransfertWidget::onFileTransferCancelled(int FriendId, int FileNum, ToxFile::FileDirection Direction)
|
||||
{
|
||||
if (File != file)
|
||||
if (FileNum != fileNum || FriendId != friendId || Direction != direction)
|
||||
return;
|
||||
disconnect(topright);
|
||||
disconnect(Widget::getInstance()->getCore(),0,this,0);
|
||||
progress->hide();
|
||||
speed->hide();
|
||||
eta->hide();
|
||||
@ -122,11 +147,12 @@ void FileTransfertWidget::onFileTransferCancelled(ToxFile* File)
|
||||
setPalette(toxred);
|
||||
}
|
||||
|
||||
void FileTransfertWidget::onFileTransferFinished(ToxFile* File)
|
||||
void FileTransfertWidget::onFileTransferFinished(ToxFile File)
|
||||
{
|
||||
if (File != file)
|
||||
if (File.fileNum != fileNum || File.friendId != friendId || File.direction != direction)
|
||||
return;
|
||||
disconnect(topright);
|
||||
topright->disconnect();
|
||||
disconnect(Widget::getInstance()->getCore(),0,this,0);
|
||||
progress->hide();
|
||||
speed->hide();
|
||||
eta->hide();
|
||||
@ -137,9 +163,55 @@ void FileTransfertWidget::onFileTransferFinished(ToxFile* File)
|
||||
QPalette toxgreen;
|
||||
toxgreen.setColor(QPalette::Window, QColor(107,194,96)); // Tox Green
|
||||
setPalette(toxgreen);
|
||||
|
||||
if (File.direction == ToxFile::RECEIVING)
|
||||
{
|
||||
QFile saveFile(savePath);
|
||||
if (!saveFile.open(QIODevice::WriteOnly))
|
||||
return;
|
||||
saveFile.write(File.fileData);
|
||||
saveFile.close();
|
||||
|
||||
QPixmap preview;
|
||||
if (preview.loadFromData(File.fileData))
|
||||
{
|
||||
preview = preview.scaledToHeight(40);
|
||||
pic->setPixmap(preview);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileTransfertWidget::cancelTransfer()
|
||||
{
|
||||
Widget::getInstance()->getCore()->cancelFileSend(file);
|
||||
Widget::getInstance()->getCore()->cancelFileSend(friendId, fileNum);
|
||||
}
|
||||
|
||||
void FileTransfertWidget::rejectRecvRequest()
|
||||
{
|
||||
Widget::getInstance()->getCore()->rejectFileRecvRequest(friendId, fileNum);
|
||||
onFileTransferCancelled(friendId, fileNum, direction);
|
||||
}
|
||||
|
||||
void FileTransfertWidget::acceptRecvRequest()
|
||||
{
|
||||
QString path = QFileDialog::getSaveFileName(0,"Save a file",QDir::currentPath()+'/'+filename->text());
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
savePath = path;
|
||||
|
||||
bottomright->setIcon(QIcon("img/button icons/pause_2x.png"));
|
||||
bottomright->disconnect();
|
||||
connect(bottomright, SIGNAL(clicked()), this, SLOT(pauseResumeRecv()));
|
||||
Widget::getInstance()->getCore()->acceptFileRecvRequest(friendId, fileNum);
|
||||
}
|
||||
|
||||
void FileTransfertWidget::pauseResumeRecv()
|
||||
{
|
||||
Widget::getInstance()->getCore()->pauseResumeFileRecv(friendId, fileNum);
|
||||
}
|
||||
|
||||
void FileTransfertWidget::pauseResumeSend()
|
||||
{
|
||||
Widget::getInstance()->getCore()->pauseResumeFileSend(friendId, fileNum);
|
||||
}
|
||||
|
@ -17,15 +17,19 @@ class FileTransfertWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FileTransfertWidget(ToxFile* File);
|
||||
FileTransfertWidget(ToxFile File);
|
||||
|
||||
public slots:
|
||||
void onFileTransferInfo(ToxFile* File);
|
||||
void onFileTransferCancelled(ToxFile* File);
|
||||
void onFileTransferFinished(ToxFile* File);
|
||||
void onFileTransferInfo(int FriendId, int FileNum, int Filesize, int BytesSent, ToxFile::FileDirection Direction);
|
||||
void onFileTransferCancelled(int FriendId, int FileNum, ToxFile::FileDirection Direction);
|
||||
void onFileTransferFinished(ToxFile File);
|
||||
|
||||
private slots:
|
||||
void cancelTransfer();
|
||||
void rejectRecvRequest();
|
||||
void acceptRecvRequest();
|
||||
void pauseResumeRecv();
|
||||
void pauseResumeSend();
|
||||
|
||||
private:
|
||||
QString getHumanReadableSize(int size);
|
||||
@ -34,11 +38,14 @@ private:
|
||||
QLabel *pic, *filename, *size, *speed, *eta;
|
||||
QPushButton *topright, *bottomright;
|
||||
QProgressBar *progress;
|
||||
ToxFile* file;
|
||||
QHBoxLayout *mainLayout, *textLayout;
|
||||
QVBoxLayout *infoLayout, *buttonLayout;
|
||||
QDateTime lastUpdate;
|
||||
long long lastBytesSent;
|
||||
int fileNum;
|
||||
int friendId;
|
||||
QString savePath;
|
||||
ToxFile::FileDirection direction;
|
||||
};
|
||||
|
||||
#endif // FILETRANSFERTWIDGET_H
|
||||
|
7
main.cpp
7
main.cpp
@ -15,3 +15,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
/** TODO
|
||||
*
|
||||
* Sort the friend list by status, online first then busy then offline
|
||||
* Don't do anything if a friend is disconnected, don't print to the chat
|
||||
*
|
||||
*/
|
||||
|
10
widget.cpp
10
widget.cpp
@ -37,6 +37,8 @@ Widget::Widget(QWidget *parent) :
|
||||
qRegisterMetaType<Status>("Status");
|
||||
qRegisterMetaType<uint8_t>("uint8_t");
|
||||
qRegisterMetaType<int32_t>("int32_t");
|
||||
qRegisterMetaType<ToxFile>("ToxFile");
|
||||
qRegisterMetaType<ToxFile::FileDirection>("ToxFile::FileDirection");
|
||||
|
||||
core = new Core();
|
||||
coreThread = new QThread(this);
|
||||
@ -51,6 +53,7 @@ Widget::Widget(QWidget *parent) :
|
||||
connect(core, &Core::statusMessageSet, this, &Widget::setStatusMessage);
|
||||
connect(core, &Core::friendAddressGenerated, &settingsForm, &SettingsForm::setFriendAddress);
|
||||
connect(core, &Core::friendAdded, this, &Widget::addFriend);
|
||||
connect(core, &Core::failedToAddFriend, this, &Widget::addFriendFailed);
|
||||
connect(core, &Core::friendStatusChanged, this, &Widget::onFriendStatusChanged);
|
||||
connect(core, &Core::friendUsernameChanged, this, &Widget::onFriendUsernameChanged);
|
||||
connect(core, &Core::friendStatusChanged, this, &Widget::onFriendStatusChanged);
|
||||
@ -217,6 +220,7 @@ void Widget::setStatusMessage(const QString &statusMessage)
|
||||
|
||||
void Widget::addFriend(int friendId, const QString &userId)
|
||||
{
|
||||
qDebug() << "Adding friend with id "+userId;
|
||||
Friend* newfriend = FriendList::addFriend(friendId, userId);
|
||||
QWidget* widget = ui->friendList->widget();
|
||||
QLayout* layout = widget->layout();
|
||||
@ -225,6 +229,12 @@ void Widget::addFriend(int friendId, const QString &userId)
|
||||
connect(newfriend->widget, SIGNAL(removeFriend(int)), this, SLOT(removeFriend(int)));
|
||||
connect(newfriend->chatForm, SIGNAL(sendMessage(int,QString)), core, SLOT(sendMessage(int,QString)));
|
||||
connect(newfriend->chatForm, SIGNAL(sendFile(int32_t,QString,QByteArray)), core, SLOT(sendFile(int32_t,QString,QByteArray)));
|
||||
connect(core, &Core::fileReceiveRequested, newfriend->chatForm, &ChatForm::onFileRecvRequest);
|
||||
}
|
||||
|
||||
void Widget::addFriendFailed(const QString&)
|
||||
{
|
||||
QMessageBox::critical(0,"Error","Couldn't request friendship");
|
||||
}
|
||||
|
||||
void Widget::onFriendStatusChanged(int friendId, Status status)
|
||||
|
1
widget.h
1
widget.h
@ -53,6 +53,7 @@ private slots:
|
||||
void setUsername(const QString& username);
|
||||
void setStatusMessage(const QString &statusMessage);
|
||||
void addFriend(int friendId, const QString& userId);
|
||||
void addFriendFailed(const QString& userId);
|
||||
void onFriendStatusChanged(int friendId, Status status);
|
||||
void onFriendStatusMessageChanged(int friendId, const QString& message);
|
||||
void onFriendUsernameChanged(int friendId, const QString& username);
|
||||
|
Loading…
x
Reference in New Issue
Block a user