mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
refactor(core): make CoreFile its own independent class
This paves the way for better testability of Core as well as CoreFile.
This commit is contained in:
parent
f03262e98b
commit
a4ad8c71b8
|
@ -21,6 +21,7 @@
|
||||||
#include "ui_filetransferwidget.h"
|
#include "ui_filetransferwidget.h"
|
||||||
|
|
||||||
#include "src/core/core.h"
|
#include "src/core/core.h"
|
||||||
|
#include "src/core/corefile.h"
|
||||||
#include "src/persistence/settings.h"
|
#include "src/persistence/settings.h"
|
||||||
#include "src/widget/gui.h"
|
#include "src/widget/gui.h"
|
||||||
#include "src/widget/style.h"
|
#include "src/widget/style.h"
|
||||||
|
@ -85,19 +86,21 @@ FileTransferWidget::FileTransferWidget(QWidget* parent, ToxFile file)
|
||||||
update();
|
update();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(Core::getInstance(), &Core::fileTransferInfo, this,
|
CoreFile* coreFile = Core::getInstance()->getCoreFile();
|
||||||
|
|
||||||
|
connect(coreFile, &CoreFile::fileTransferInfo, this,
|
||||||
&FileTransferWidget::onFileTransferInfo);
|
&FileTransferWidget::onFileTransferInfo);
|
||||||
connect(Core::getInstance(), &Core::fileTransferAccepted, this,
|
connect(coreFile, &CoreFile::fileTransferAccepted, this,
|
||||||
&FileTransferWidget::onFileTransferAccepted);
|
&FileTransferWidget::onFileTransferAccepted);
|
||||||
connect(Core::getInstance(), &Core::fileTransferCancelled, this,
|
connect(coreFile, &CoreFile::fileTransferCancelled, this,
|
||||||
&FileTransferWidget::onFileTransferCancelled);
|
&FileTransferWidget::onFileTransferCancelled);
|
||||||
connect(Core::getInstance(), &Core::fileTransferPaused, this,
|
connect(coreFile, &CoreFile::fileTransferPaused, this,
|
||||||
&FileTransferWidget::onFileTransferPaused);
|
&FileTransferWidget::onFileTransferPaused);
|
||||||
connect(Core::getInstance(), &Core::fileTransferFinished, this,
|
connect(coreFile, &CoreFile::fileTransferFinished, this,
|
||||||
&FileTransferWidget::onFileTransferFinished);
|
&FileTransferWidget::onFileTransferFinished);
|
||||||
connect(Core::getInstance(), &Core::fileTransferRemotePausedUnpaused, this,
|
connect(coreFile, &CoreFile::fileTransferRemotePausedUnpaused, this,
|
||||||
&FileTransferWidget::fileTransferRemotePausedUnpaused);
|
&FileTransferWidget::fileTransferRemotePausedUnpaused);
|
||||||
connect(Core::getInstance(), &Core::fileTransferBrokenUnbroken, this,
|
connect(coreFile, &CoreFile::fileTransferBrokenUnbroken, this,
|
||||||
&FileTransferWidget::fileTransferBrokenUnbroken);
|
&FileTransferWidget::fileTransferBrokenUnbroken);
|
||||||
connect(ui->leftButton, &QPushButton::clicked, this, &FileTransferWidget::onLeftButtonClicked);
|
connect(ui->leftButton, &QPushButton::clicked, this, &FileTransferWidget::onLeftButtonClicked);
|
||||||
connect(ui->rightButton, &QPushButton::clicked, this, &FileTransferWidget::onRightButtonClicked);
|
connect(ui->rightButton, &QPushButton::clicked, this, &FileTransferWidget::onRightButtonClicked);
|
||||||
|
@ -149,7 +152,8 @@ void FileTransferWidget::autoAcceptTransfer(const QString& path)
|
||||||
// Do not automatically accept the file-transfer if the path is not writable.
|
// Do not automatically accept the file-transfer if the path is not writable.
|
||||||
// The user can still accept it manually.
|
// The user can still accept it manually.
|
||||||
if (tryRemoveFile(filepath)) {
|
if (tryRemoveFile(filepath)) {
|
||||||
Core::getInstance()->acceptFileRecvRequest(fileInfo.friendId, fileInfo.fileNum, filepath);
|
CoreFile* coreFile = Core::getInstance()->getCoreFile();
|
||||||
|
coreFile->acceptFileRecvRequest(fileInfo.friendId, fileInfo.fileNum, filepath);
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Cannot write to " << filepath;
|
qWarning() << "Cannot write to " << filepath;
|
||||||
}
|
}
|
||||||
|
@ -176,7 +180,8 @@ void FileTransferWidget::acceptTransfer(const QString& filepath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// everything ok!
|
// everything ok!
|
||||||
Core::getInstance()->acceptFileRecvRequest(fileInfo.friendId, fileInfo.fileNum, filepath);
|
CoreFile* coreFile = Core::getInstance()->getCoreFile();
|
||||||
|
coreFile->acceptFileRecvRequest(fileInfo.friendId, fileInfo.fileNum, filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileTransferWidget::setBackgroundColor(const QColor& c, bool whiteFont)
|
void FileTransferWidget::setBackgroundColor(const QColor& c, bool whiteFont)
|
||||||
|
@ -464,7 +469,7 @@ void FileTransferWidget::updateSignals(ToxFile const& file)
|
||||||
case ToxFile::BROKEN:
|
case ToxFile::BROKEN:
|
||||||
case ToxFile::FINISHED:
|
case ToxFile::FINISHED:
|
||||||
active = false;
|
active = false;
|
||||||
disconnect(Core::getInstance(), nullptr, this, nullptr);
|
disconnect(Core::getInstance()->getCoreFile(), nullptr, this, nullptr);
|
||||||
break;
|
break;
|
||||||
case ToxFile::INITIALIZING:
|
case ToxFile::INITIALIZING:
|
||||||
case ToxFile::PAUSED:
|
case ToxFile::PAUSED:
|
||||||
|
@ -553,22 +558,23 @@ void FileTransferWidget::setupButtons(ToxFile const& file)
|
||||||
|
|
||||||
void FileTransferWidget::handleButton(QPushButton* btn)
|
void FileTransferWidget::handleButton(QPushButton* btn)
|
||||||
{
|
{
|
||||||
|
CoreFile* coreFile = Core::getInstance()->getCoreFile();
|
||||||
if (fileInfo.direction == ToxFile::SENDING) {
|
if (fileInfo.direction == ToxFile::SENDING) {
|
||||||
if (btn->objectName() == "cancel") {
|
if (btn->objectName() == "cancel") {
|
||||||
Core::getInstance()->cancelFileSend(fileInfo.friendId, fileInfo.fileNum);
|
coreFile->cancelFileSend(fileInfo.friendId, fileInfo.fileNum);
|
||||||
} else if (btn->objectName() == "pause") {
|
} else if (btn->objectName() == "pause") {
|
||||||
Core::getInstance()->pauseResumeFile(fileInfo.friendId, fileInfo.fileNum);
|
coreFile->pauseResumeFile(fileInfo.friendId, fileInfo.fileNum);
|
||||||
} else if (btn->objectName() == "resume") {
|
} else if (btn->objectName() == "resume") {
|
||||||
Core::getInstance()->pauseResumeFile(fileInfo.friendId, fileInfo.fileNum);
|
coreFile->pauseResumeFile(fileInfo.friendId, fileInfo.fileNum);
|
||||||
}
|
}
|
||||||
} else // receiving or paused
|
} else // receiving or paused
|
||||||
{
|
{
|
||||||
if (btn->objectName() == "cancel") {
|
if (btn->objectName() == "cancel") {
|
||||||
Core::getInstance()->cancelFileRecv(fileInfo.friendId, fileInfo.fileNum);
|
coreFile->cancelFileRecv(fileInfo.friendId, fileInfo.fileNum);
|
||||||
} else if (btn->objectName() == "pause") {
|
} else if (btn->objectName() == "pause") {
|
||||||
Core::getInstance()->pauseResumeFile(fileInfo.friendId, fileInfo.fileNum);
|
coreFile->pauseResumeFile(fileInfo.friendId, fileInfo.fileNum);
|
||||||
} else if (btn->objectName() == "resume") {
|
} else if (btn->objectName() == "resume") {
|
||||||
Core::getInstance()->pauseResumeFile(fileInfo.friendId, fileInfo.fileNum);
|
coreFile->pauseResumeFile(fileInfo.friendId, fileInfo.fileNum);
|
||||||
} else if (btn->objectName() == "accept") {
|
} else if (btn->objectName() == "accept") {
|
||||||
QString path =
|
QString path =
|
||||||
QFileDialog::getSaveFileName(Q_NULLPTR,
|
QFileDialog::getSaveFileName(Q_NULLPTR,
|
||||||
|
|
|
@ -165,10 +165,6 @@ void Core::registerCallbacks(Tox* tox)
|
||||||
tox_callback_conference_peer_list_changed(tox, onGroupPeerListChange);
|
tox_callback_conference_peer_list_changed(tox, onGroupPeerListChange);
|
||||||
tox_callback_conference_peer_name(tox, onGroupPeerNameChange);
|
tox_callback_conference_peer_name(tox, onGroupPeerNameChange);
|
||||||
tox_callback_conference_title(tox, onGroupTitleChange);
|
tox_callback_conference_title(tox, onGroupTitleChange);
|
||||||
tox_callback_file_chunk_request(tox, CoreFile::onFileDataCallback);
|
|
||||||
tox_callback_file_recv(tox, CoreFile::onFileReceiveCallback);
|
|
||||||
tox_callback_file_recv_chunk(tox, CoreFile::onFileRecvChunkCallback);
|
|
||||||
tox_callback_file_recv_control(tox, CoreFile::onFileControlCallback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -293,6 +289,16 @@ ToxCorePtr Core::makeToxCore(const QByteArray& savedata, const ICoreSettings* co
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create CoreFile
|
||||||
|
core->file = CoreFile::makeCoreFile(core.get(), core->tox.get(), core->coreLoopLock);
|
||||||
|
if (!core->file) {
|
||||||
|
qCritical() << "CoreFile failed to start";
|
||||||
|
if (err) {
|
||||||
|
*err = ToxCoreErrors::FAILED_TO_START;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
registerCallbacks(core->tox.get());
|
registerCallbacks(core->tox.get());
|
||||||
|
|
||||||
// connect the thread with the Core
|
// connect the thread with the Core
|
||||||
|
@ -359,6 +365,11 @@ CoreAV* Core::getAv()
|
||||||
return av.get();
|
return av.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoreFile* Core::getCoreFile() const
|
||||||
|
{
|
||||||
|
return file.get();
|
||||||
|
}
|
||||||
|
|
||||||
/* Using the now commented out statements in checkConnection(), I watched how
|
/* Using the now commented out statements in checkConnection(), I watched how
|
||||||
* many ticks disconnects-after-initial-connect lasted. Out of roughly 15 trials,
|
* many ticks disconnects-after-initial-connect lasted. Out of roughly 15 trials,
|
||||||
* 5 disconnected; 4 were DCd for less than 20 ticks, while the 5th was ~50 ticks.
|
* 5 disconnected; 4 were DCd for less than 20 ticks, while the 5th was ~50 ticks.
|
||||||
|
@ -394,7 +405,7 @@ void Core::process()
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned sleeptime =
|
unsigned sleeptime =
|
||||||
qMin(tox_iteration_interval(tox.get()), CoreFile::corefileIterationInterval());
|
qMin(tox_iteration_interval(tox.get()), getCoreFile()->corefileIterationInterval());
|
||||||
toxTimer->start(sleeptime);
|
toxTimer->start(sleeptime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,15 +524,15 @@ void Core::onUserStatusChanged(Tox*, uint32_t friendId, Tox_User_Status userstat
|
||||||
emit static_cast<Core*>(core)->friendStatusChanged(friendId, status);
|
emit static_cast<Core*>(core)->friendStatusChanged(friendId, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::onConnectionStatusChanged(Tox*, uint32_t friendId, Tox_Connection status, void* core)
|
void Core::onConnectionStatusChanged(Tox*, uint32_t friendId, Tox_Connection status, void* vCore)
|
||||||
{
|
{
|
||||||
|
Core* core = static_cast<Core*>(vCore);
|
||||||
Status friendStatus = status != TOX_CONNECTION_NONE ? Status::Online : Status::Offline;
|
Status friendStatus = status != TOX_CONNECTION_NONE ? Status::Online : Status::Offline;
|
||||||
// Ignore Online because it will be emited from onUserStatusChanged
|
// Ignore Online because it will be emited from onUserStatusChanged
|
||||||
bool isOffline = friendStatus == Status::Offline;
|
bool isOffline = friendStatus == Status::Offline;
|
||||||
if (isOffline) {
|
if (isOffline) {
|
||||||
emit static_cast<Core*>(core)->friendStatusChanged(friendId, friendStatus);
|
emit core->friendStatusChanged(friendId, friendStatus);
|
||||||
static_cast<Core*>(core)->checkLastOnline(friendId);
|
core->checkLastOnline(friendId);
|
||||||
CoreFile::onConnectionStatusChanged(static_cast<Core*>(core), friendId, !isOffline);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -757,55 +768,6 @@ void Core::changeGroupTitle(int groupId, const QString& title)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::sendFile(uint32_t friendId, QString filename, QString filePath, long long filesize)
|
|
||||||
{
|
|
||||||
QMutexLocker ml{&coreLoopLock};
|
|
||||||
|
|
||||||
CoreFile::sendFile(this, friendId, filename, filePath, filesize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::sendAvatarFile(uint32_t friendId, const QByteArray& data)
|
|
||||||
{
|
|
||||||
QMutexLocker ml{&coreLoopLock};
|
|
||||||
|
|
||||||
CoreFile::sendAvatarFile(this, friendId, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::pauseResumeFile(uint32_t friendId, uint32_t fileNum)
|
|
||||||
{
|
|
||||||
QMutexLocker ml{&coreLoopLock};
|
|
||||||
|
|
||||||
CoreFile::pauseResumeFile(this, friendId, fileNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::cancelFileSend(uint32_t friendId, uint32_t fileNum)
|
|
||||||
{
|
|
||||||
QMutexLocker ml{&coreLoopLock};
|
|
||||||
|
|
||||||
CoreFile::cancelFileSend(this, friendId, fileNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::cancelFileRecv(uint32_t friendId, uint32_t fileNum)
|
|
||||||
{
|
|
||||||
QMutexLocker ml{&coreLoopLock};
|
|
||||||
|
|
||||||
CoreFile::cancelFileRecv(this, friendId, fileNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::rejectFileRecvRequest(uint32_t friendId, uint32_t fileNum)
|
|
||||||
{
|
|
||||||
QMutexLocker ml{&coreLoopLock};
|
|
||||||
|
|
||||||
CoreFile::rejectFileRecvRequest(this, friendId, fileNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::acceptFileRecvRequest(uint32_t friendId, uint32_t fileNum, QString path)
|
|
||||||
{
|
|
||||||
QMutexLocker ml{&coreLoopLock};
|
|
||||||
|
|
||||||
CoreFile::acceptFileRecvRequest(this, friendId, fileNum, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::removeFriend(uint32_t friendId)
|
void Core::removeFriend(uint32_t friendId)
|
||||||
{
|
{
|
||||||
QMutexLocker ml{&coreLoopLock};
|
QMutexLocker ml{&coreLoopLock};
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class CoreAV;
|
class CoreAV;
|
||||||
|
class CoreFile;
|
||||||
class ICoreSettings;
|
class ICoreSettings;
|
||||||
class GroupInvite;
|
class GroupInvite;
|
||||||
class Profile;
|
class Profile;
|
||||||
|
@ -71,6 +72,7 @@ public:
|
||||||
static Core* getInstance();
|
static Core* getInstance();
|
||||||
const CoreAV* getAv() const;
|
const CoreAV* getAv() const;
|
||||||
CoreAV* getAv();
|
CoreAV* getAv();
|
||||||
|
CoreFile* getCoreFile() const;
|
||||||
~Core();
|
~Core();
|
||||||
|
|
||||||
static const QString TOX_EXT;
|
static const QString TOX_EXT;
|
||||||
|
@ -125,13 +127,6 @@ public slots:
|
||||||
bool sendAction(uint32_t friendId, const QString& action, ReceiptNum& receipt);
|
bool sendAction(uint32_t friendId, const QString& action, ReceiptNum& receipt);
|
||||||
void sendTyping(uint32_t friendId, bool typing);
|
void sendTyping(uint32_t friendId, bool typing);
|
||||||
|
|
||||||
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);
|
|
||||||
void acceptFileRecvRequest(uint32_t friendId, uint32_t fileNum, QString path);
|
|
||||||
void pauseResumeFile(uint32_t friendId, uint32_t fileNum);
|
|
||||||
|
|
||||||
void setNospam(uint32_t nospam);
|
void setNospam(uint32_t nospam);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -157,19 +152,6 @@ signals:
|
||||||
|
|
||||||
void avReady();
|
void avReady();
|
||||||
|
|
||||||
void fileSendStarted(ToxFile file);
|
|
||||||
void fileReceiveRequested(ToxFile file);
|
|
||||||
void fileTransferAccepted(ToxFile file);
|
|
||||||
void fileTransferCancelled(ToxFile file);
|
|
||||||
void fileTransferFinished(ToxFile file);
|
|
||||||
void fileUploadFinished(const QString& path);
|
|
||||||
void fileDownloadFinished(const QString& path);
|
|
||||||
void fileTransferPaused(ToxFile file);
|
|
||||||
void fileTransferInfo(ToxFile file);
|
|
||||||
void fileTransferRemotePausedUnpaused(ToxFile file, bool paused);
|
|
||||||
void fileTransferBrokenUnbroken(ToxFile file, bool broken);
|
|
||||||
void fileNameChanged(const ToxPk& friendPk);
|
|
||||||
|
|
||||||
void saveRequest();
|
void saveRequest();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -204,8 +186,6 @@ signals:
|
||||||
|
|
||||||
void failedToRemoveFriend(uint32_t friendId);
|
void failedToRemoveFriend(uint32_t friendId);
|
||||||
|
|
||||||
void fileSendFailed(uint32_t friendId, const QString& fname);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Core(QThread* coreThread);
|
Core(QThread* coreThread);
|
||||||
|
|
||||||
|
@ -221,7 +201,7 @@ private:
|
||||||
static void onUserStatusChanged(Tox* tox, uint32_t friendId, Tox_User_Status userstatus,
|
static void onUserStatusChanged(Tox* tox, uint32_t friendId, Tox_User_Status userstatus,
|
||||||
void* core);
|
void* core);
|
||||||
static void onConnectionStatusChanged(Tox* tox, uint32_t friendId, Tox_Connection status,
|
static void onConnectionStatusChanged(Tox* tox, uint32_t friendId, Tox_Connection status,
|
||||||
void* core);
|
void* vCore);
|
||||||
static void onGroupInvite(Tox* tox, uint32_t friendId, Tox_Conference_Type type,
|
static void onGroupInvite(Tox* tox, uint32_t friendId, Tox_Conference_Type type,
|
||||||
const uint8_t* cookie, size_t length, void* vCore);
|
const uint8_t* cookie, size_t length, void* vCore);
|
||||||
static void onGroupMessage(Tox* tox, uint32_t groupId, uint32_t peerId, Tox_Message_Type type,
|
static void onGroupMessage(Tox* tox, uint32_t groupId, uint32_t peerId, Tox_Message_Type type,
|
||||||
|
@ -241,7 +221,6 @@ private:
|
||||||
|
|
||||||
void checkEncryptedHistory();
|
void checkEncryptedHistory();
|
||||||
void makeTox(QByteArray savedata, ICoreSettings* s);
|
void makeTox(QByteArray savedata, ICoreSettings* s);
|
||||||
void makeAv();
|
|
||||||
void loadFriends();
|
void loadFriends();
|
||||||
void loadGroups();
|
void loadGroups();
|
||||||
void bootstrapDht();
|
void bootstrapDht();
|
||||||
|
@ -267,6 +246,7 @@ private:
|
||||||
using ToxPtr = std::unique_ptr<Tox, ToxDeleter>;
|
using ToxPtr = std::unique_ptr<Tox, ToxDeleter>;
|
||||||
ToxPtr tox;
|
ToxPtr tox;
|
||||||
|
|
||||||
|
std::unique_ptr<CoreFile> file;
|
||||||
std::unique_ptr<CoreAV> av;
|
std::unique_ptr<CoreAV> av;
|
||||||
QTimer* toxTimer = nullptr;
|
QTimer* toxTimer = nullptr;
|
||||||
// recursive, since we might call our own functions
|
// recursive, since we might call our own functions
|
||||||
|
@ -275,7 +255,6 @@ private:
|
||||||
std::unique_ptr<QThread> coreThread = nullptr;
|
std::unique_ptr<QThread> coreThread = nullptr;
|
||||||
|
|
||||||
friend class Audio; ///< Audio can access our calls directly to reduce latency
|
friend class Audio; ///< Audio can access our calls directly to reduce latency
|
||||||
friend class CoreFile; ///< CoreFile can access tox* and emit our signals
|
|
||||||
friend class CoreAV; ///< CoreAV accesses our toxav* for now
|
friend class CoreAV; ///< CoreAV accesses our toxav* for now
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,25 +22,36 @@
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "toxfile.h"
|
#include "toxfile.h"
|
||||||
#include "toxstring.h"
|
#include "toxstring.h"
|
||||||
#include "src/persistence/profile.h"
|
|
||||||
#include "src/persistence/settings.h"
|
#include "src/persistence/settings.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
#include <cassert>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class CoreFile
|
* @class CoreFile
|
||||||
* @brief Implements Core's file transfer callbacks.
|
* @brief Manages the file transfer service of toxcore
|
||||||
*
|
|
||||||
* Avoids polluting core.h with private internal callbacks.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
QMutex CoreFile::fileSendMutex;
|
CoreFilePtr CoreFile::makeCoreFile(Core *core, Tox *tox, QMutex &coreLoopLock)
|
||||||
QHash<uint64_t, ToxFile> CoreFile::fileMap;
|
{
|
||||||
using namespace std;
|
assert(core != nullptr);
|
||||||
|
assert(tox != nullptr);
|
||||||
|
connectCallbacks(*tox);
|
||||||
|
CoreFilePtr result = CoreFilePtr{new CoreFile{tox, coreLoopLock}};
|
||||||
|
connect(core, &Core::friendStatusChanged, result.get(), &CoreFile::onConnectionStatusChanged);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreFile::CoreFile(Tox *core, QMutex &coreLoopLock)
|
||||||
|
: tox{core}
|
||||||
|
, coreLoopLock{&coreLoopLock}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get corefile iteration interval.
|
* @brief Get corefile iteration interval.
|
||||||
|
@ -66,12 +77,21 @@ unsigned CoreFile::corefileIterationInterval()
|
||||||
return idleInterval;
|
return idleInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFile::sendAvatarFile(Core* core, uint32_t friendId, const QByteArray& data)
|
void CoreFile::connectCallbacks(Tox &tox)
|
||||||
{
|
{
|
||||||
QMutexLocker mlocker(&fileSendMutex);
|
// be careful not to to reconnect already used callbacks here
|
||||||
|
tox_callback_file_chunk_request(&tox, CoreFile::onFileDataCallback);
|
||||||
|
tox_callback_file_recv(&tox, CoreFile::onFileReceiveCallback);
|
||||||
|
tox_callback_file_recv_chunk(&tox, CoreFile::onFileRecvChunkCallback);
|
||||||
|
tox_callback_file_recv_control(&tox, CoreFile::onFileControlCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreFile::sendAvatarFile(uint32_t friendId, const QByteArray& data)
|
||||||
|
{
|
||||||
|
QMutexLocker{coreLoopLock};
|
||||||
|
|
||||||
if (data.isEmpty()) {
|
if (data.isEmpty()) {
|
||||||
tox_file_send(core->tox.get(), friendId, TOX_FILE_KIND_AVATAR, 0, nullptr, nullptr, 0, nullptr);
|
tox_file_send(tox, friendId, TOX_FILE_KIND_AVATAR, 0, nullptr, nullptr, 0, nullptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +101,7 @@ void CoreFile::sendAvatarFile(Core* core, uint32_t friendId, const QByteArray& d
|
||||||
uint64_t filesize = data.size();
|
uint64_t filesize = data.size();
|
||||||
|
|
||||||
Tox_Err_File_Send error;
|
Tox_Err_File_Send error;
|
||||||
uint32_t fileNum = tox_file_send(core->tox.get(), friendId, TOX_FILE_KIND_AVATAR, filesize,
|
uint32_t fileNum = tox_file_send(tox, friendId, TOX_FILE_KIND_AVATAR, filesize,
|
||||||
avatarHash, avatarHash, TOX_HASH_LENGTH, &error);
|
avatarHash, avatarHash, TOX_HASH_LENGTH, &error);
|
||||||
|
|
||||||
switch (error) {
|
switch (error) {
|
||||||
|
@ -111,22 +131,23 @@ void CoreFile::sendAvatarFile(Core* core, uint32_t friendId, const QByteArray& d
|
||||||
file.fileKind = TOX_FILE_KIND_AVATAR;
|
file.fileKind = TOX_FILE_KIND_AVATAR;
|
||||||
file.avatarData = data;
|
file.avatarData = data;
|
||||||
file.resumeFileId.resize(TOX_FILE_ID_LENGTH);
|
file.resumeFileId.resize(TOX_FILE_ID_LENGTH);
|
||||||
tox_file_get_file_id(core->tox.get(), friendId, fileNum, (uint8_t*)file.resumeFileId.data(),
|
tox_file_get_file_id(tox, friendId, fileNum, (uint8_t*)file.resumeFileId.data(),
|
||||||
nullptr);
|
nullptr);
|
||||||
addFile(friendId, fileNum, file);
|
addFile(friendId, fileNum, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFile::sendFile(Core* core, uint32_t friendId, QString filename, QString filePath,
|
void CoreFile::sendFile(uint32_t friendId, QString filename, QString filePath,
|
||||||
long long filesize)
|
long long filesize)
|
||||||
{
|
{
|
||||||
QMutexLocker mlocker(&fileSendMutex);
|
QMutexLocker{coreLoopLock};
|
||||||
|
|
||||||
ToxString fileName(filename);
|
ToxString fileName(filename);
|
||||||
TOX_ERR_FILE_SEND sendErr;
|
TOX_ERR_FILE_SEND sendErr;
|
||||||
uint32_t fileNum = tox_file_send(core->tox.get(), friendId, TOX_FILE_KIND_DATA, filesize,
|
uint32_t fileNum = tox_file_send(tox, friendId, TOX_FILE_KIND_DATA, filesize,
|
||||||
nullptr, fileName.data(), fileName.size(), &sendErr);
|
nullptr, fileName.data(), fileName.size(), &sendErr);
|
||||||
if (sendErr != TOX_ERR_FILE_SEND_OK) {
|
if (sendErr != TOX_ERR_FILE_SEND_OK) {
|
||||||
qWarning() << "sendFile: Can't create the Tox file sender (" << sendErr << ")";
|
qWarning() << "sendFile: Can't create the Tox file sender (" << sendErr << ")";
|
||||||
emit core->fileSendFailed(friendId, fileName.getQString());
|
emit fileSendFailed(friendId, fileName.getQString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
qDebug() << QString("sendFile: Created file sender %1 with friend %2").arg(fileNum).arg(friendId);
|
qDebug() << QString("sendFile: Created file sender %1 with friend %2").arg(fileNum).arg(friendId);
|
||||||
|
@ -134,7 +155,7 @@ void CoreFile::sendFile(Core* core, uint32_t friendId, QString filename, QString
|
||||||
ToxFile file{fileNum, friendId, fileName.getQString(), filePath, ToxFile::SENDING};
|
ToxFile file{fileNum, friendId, fileName.getQString(), filePath, ToxFile::SENDING};
|
||||||
file.filesize = filesize;
|
file.filesize = filesize;
|
||||||
file.resumeFileId.resize(TOX_FILE_ID_LENGTH);
|
file.resumeFileId.resize(TOX_FILE_ID_LENGTH);
|
||||||
tox_file_get_file_id(core->tox.get(), friendId, fileNum, (uint8_t*)file.resumeFileId.data(),
|
tox_file_get_file_id(tox, friendId, fileNum, (uint8_t*)file.resumeFileId.data(),
|
||||||
nullptr);
|
nullptr);
|
||||||
if (!file.open(false)) {
|
if (!file.open(false)) {
|
||||||
qWarning() << QString("sendFile: Can't open file, error: %1").arg(file.file->errorString());
|
qWarning() << QString("sendFile: Can't open file, error: %1").arg(file.file->errorString());
|
||||||
|
@ -142,11 +163,13 @@ void CoreFile::sendFile(Core* core, uint32_t friendId, QString filename, QString
|
||||||
|
|
||||||
addFile(friendId, fileNum, file);
|
addFile(friendId, fileNum, file);
|
||||||
|
|
||||||
emit core->fileSendStarted(file);
|
emit fileSendStarted(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFile::pauseResumeFile(Core* core, uint32_t friendId, uint32_t fileId)
|
void CoreFile::pauseResumeFile(uint32_t friendId, uint32_t fileId)
|
||||||
{
|
{
|
||||||
|
QMutexLocker{coreLoopLock};
|
||||||
|
|
||||||
ToxFile* file = findFile(friendId, fileId);
|
ToxFile* file = findFile(friendId, fileId);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
qWarning("pauseResumeFileSend: No such file in queue");
|
qWarning("pauseResumeFileSend: No such file in queue");
|
||||||
|
@ -162,23 +185,25 @@ void CoreFile::pauseResumeFile(Core* core, uint32_t friendId, uint32_t fileId)
|
||||||
|
|
||||||
if (file->pauseStatus.paused()) {
|
if (file->pauseStatus.paused()) {
|
||||||
file->status = ToxFile::PAUSED;
|
file->status = ToxFile::PAUSED;
|
||||||
emit core->fileTransferPaused(*file);
|
emit fileTransferPaused(*file);
|
||||||
} else {
|
} else {
|
||||||
file->status = ToxFile::TRANSMITTING;
|
file->status = ToxFile::TRANSMITTING;
|
||||||
emit core->fileTransferAccepted(*file);
|
emit fileTransferAccepted(*file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file->pauseStatus.localPaused()) {
|
if (file->pauseStatus.localPaused()) {
|
||||||
tox_file_control(core->tox.get(), file->friendId, file->fileNum, TOX_FILE_CONTROL_PAUSE,
|
tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_PAUSE,
|
||||||
nullptr);
|
nullptr);
|
||||||
} else {
|
} else {
|
||||||
tox_file_control(core->tox.get(), file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME,
|
tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME,
|
||||||
nullptr);
|
nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFile::cancelFileSend(Core* core, uint32_t friendId, uint32_t fileId)
|
void CoreFile::cancelFileSend(uint32_t friendId, uint32_t fileId)
|
||||||
{
|
{
|
||||||
|
QMutexLocker{coreLoopLock};
|
||||||
|
|
||||||
ToxFile* file = findFile(friendId, fileId);
|
ToxFile* file = findFile(friendId, fileId);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
qWarning("cancelFileSend: No such file in queue");
|
qWarning("cancelFileSend: No such file in queue");
|
||||||
|
@ -186,39 +211,45 @@ void CoreFile::cancelFileSend(Core* core, uint32_t friendId, uint32_t fileId)
|
||||||
}
|
}
|
||||||
|
|
||||||
file->status = ToxFile::CANCELED;
|
file->status = ToxFile::CANCELED;
|
||||||
emit core->fileTransferCancelled(*file);
|
emit fileTransferCancelled(*file);
|
||||||
tox_file_control(core->tox.get(), file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr);
|
tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr);
|
||||||
removeFile(friendId, fileId);
|
removeFile(friendId, fileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFile::cancelFileRecv(Core* core, uint32_t friendId, uint32_t fileId)
|
void CoreFile::cancelFileRecv(uint32_t friendId, uint32_t fileId)
|
||||||
{
|
{
|
||||||
|
QMutexLocker{coreLoopLock};
|
||||||
|
|
||||||
ToxFile* file = findFile(friendId, fileId);
|
ToxFile* file = findFile(friendId, fileId);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
qWarning("cancelFileRecv: No such file in queue");
|
qWarning("cancelFileRecv: No such file in queue");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
file->status = ToxFile::CANCELED;
|
file->status = ToxFile::CANCELED;
|
||||||
emit core->fileTransferCancelled(*file);
|
emit fileTransferCancelled(*file);
|
||||||
tox_file_control(core->tox.get(), file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr);
|
tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr);
|
||||||
removeFile(friendId, fileId);
|
removeFile(friendId, fileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFile::rejectFileRecvRequest(Core* core, uint32_t friendId, uint32_t fileId)
|
void CoreFile::rejectFileRecvRequest(uint32_t friendId, uint32_t fileId)
|
||||||
{
|
{
|
||||||
|
QMutexLocker{coreLoopLock};
|
||||||
|
|
||||||
ToxFile* file = findFile(friendId, fileId);
|
ToxFile* file = findFile(friendId, fileId);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
qWarning("rejectFileRecvRequest: No such file in queue");
|
qWarning("rejectFileRecvRequest: No such file in queue");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
file->status = ToxFile::CANCELED;
|
file->status = ToxFile::CANCELED;
|
||||||
emit core->fileTransferCancelled(*file);
|
emit fileTransferCancelled(*file);
|
||||||
tox_file_control(core->tox.get(), file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr);
|
tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr);
|
||||||
removeFile(friendId, fileId);
|
removeFile(friendId, fileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFile::acceptFileRecvRequest(Core* core, uint32_t friendId, uint32_t fileId, QString path)
|
void CoreFile::acceptFileRecvRequest(uint32_t friendId, uint32_t fileId, QString path)
|
||||||
{
|
{
|
||||||
|
QMutexLocker{coreLoopLock};
|
||||||
|
|
||||||
ToxFile* file = findFile(friendId, fileId);
|
ToxFile* file = findFile(friendId, fileId);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
qWarning("acceptFileRecvRequest: No such file in queue");
|
qWarning("acceptFileRecvRequest: No such file in queue");
|
||||||
|
@ -230,12 +261,14 @@ void CoreFile::acceptFileRecvRequest(Core* core, uint32_t friendId, uint32_t fil
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
file->status = ToxFile::TRANSMITTING;
|
file->status = ToxFile::TRANSMITTING;
|
||||||
emit core->fileTransferAccepted(*file);
|
emit fileTransferAccepted(*file);
|
||||||
tox_file_control(core->tox.get(), file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr);
|
tox_file_control(tox, file->friendId, file->fileNum, TOX_FILE_CONTROL_RESUME, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ToxFile* CoreFile::findFile(uint32_t friendId, uint32_t fileId)
|
ToxFile* CoreFile::findFile(uint32_t friendId, uint32_t fileId)
|
||||||
{
|
{
|
||||||
|
QMutexLocker{coreLoopLock};
|
||||||
|
|
||||||
uint64_t key = getFriendKey(friendId, fileId);
|
uint64_t key = getFriendKey(friendId, fileId);
|
||||||
if (fileMap.contains(key)) {
|
if (fileMap.contains(key)) {
|
||||||
return &fileMap[key];
|
return &fileMap[key];
|
||||||
|
@ -276,11 +309,12 @@ QString CoreFile::getCleanFileName(QString filename)
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFile::onFileReceiveCallback(Tox*, uint32_t friendId, uint32_t fileId, uint32_t kind,
|
void CoreFile::onFileReceiveCallback(Tox* tox, uint32_t friendId, uint32_t fileId, uint32_t kind,
|
||||||
uint64_t filesize, const uint8_t* fname, size_t fnameLen,
|
uint64_t filesize, const uint8_t* fname, size_t fnameLen,
|
||||||
void* vCore)
|
void* vCore)
|
||||||
{
|
{
|
||||||
Core* core = static_cast<Core*>(vCore);
|
Core* core = static_cast<Core*>(vCore);
|
||||||
|
CoreFile* coreFile = core->getCoreFile();
|
||||||
auto filename = ToxString(fname, fnameLen);
|
auto filename = ToxString(fname, fnameLen);
|
||||||
const ToxPk friendPk = core->getFriendPublicKey(friendId);
|
const ToxPk friendPk = core->getFriendPublicKey(friendId);
|
||||||
|
|
||||||
|
@ -294,7 +328,7 @@ void CoreFile::onFileReceiveCallback(Tox*, uint32_t friendId, uint32_t fileId, u
|
||||||
static_assert(TOX_HASH_LENGTH <= TOX_FILE_ID_LENGTH,
|
static_assert(TOX_HASH_LENGTH <= TOX_FILE_ID_LENGTH,
|
||||||
"TOX_HASH_LENGTH > TOX_FILE_ID_LENGTH!");
|
"TOX_HASH_LENGTH > TOX_FILE_ID_LENGTH!");
|
||||||
uint8_t avatarHash[TOX_FILE_ID_LENGTH];
|
uint8_t avatarHash[TOX_FILE_ID_LENGTH];
|
||||||
tox_file_get_file_id(core->tox.get(), friendId, fileId, avatarHash, nullptr);
|
tox_file_get_file_id(tox, friendId, fileId, avatarHash, nullptr);
|
||||||
QByteArray avatarBytes{static_cast<const char*>(static_cast<const void*>(avatarHash)),
|
QByteArray avatarBytes{static_cast<const char*>(static_cast<const void*>(avatarHash)),
|
||||||
TOX_HASH_LENGTH};
|
TOX_HASH_LENGTH};
|
||||||
emit core->fileAvatarOfferReceived(friendId, fileId, avatarBytes);
|
emit core->fileAvatarOfferReceived(friendId, fileId, avatarBytes);
|
||||||
|
@ -305,7 +339,7 @@ void CoreFile::onFileReceiveCallback(Tox*, uint32_t friendId, uint32_t fileId, u
|
||||||
if (cleanFileName != filename.getQString()) {
|
if (cleanFileName != filename.getQString()) {
|
||||||
qDebug() << QStringLiteral("Cleaned filename");
|
qDebug() << QStringLiteral("Cleaned filename");
|
||||||
filename = ToxString(cleanFileName);
|
filename = ToxString(cleanFileName);
|
||||||
emit core->fileNameChanged(friendPk);
|
emit coreFile->fileNameChanged(friendPk);
|
||||||
} else {
|
} else {
|
||||||
qDebug() << QStringLiteral("filename already clean");
|
qDebug() << QStringLiteral("filename already clean");
|
||||||
}
|
}
|
||||||
|
@ -316,24 +350,23 @@ void CoreFile::onFileReceiveCallback(Tox*, uint32_t friendId, uint32_t fileId, u
|
||||||
file.filesize = filesize;
|
file.filesize = filesize;
|
||||||
file.fileKind = kind;
|
file.fileKind = kind;
|
||||||
file.resumeFileId.resize(TOX_FILE_ID_LENGTH);
|
file.resumeFileId.resize(TOX_FILE_ID_LENGTH);
|
||||||
tox_file_get_file_id(core->tox.get(), friendId, fileId, (uint8_t*)file.resumeFileId.data(),
|
tox_file_get_file_id(tox, friendId, fileId, (uint8_t*)file.resumeFileId.data(),
|
||||||
nullptr);
|
nullptr);
|
||||||
addFile(friendId, fileId, file);
|
coreFile->addFile(friendId, fileId, file);
|
||||||
if (kind != TOX_FILE_KIND_AVATAR)
|
if (kind != TOX_FILE_KIND_AVATAR) {
|
||||||
emit core->fileReceiveRequested(file);
|
emit coreFile->fileReceiveRequested(file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(sudden6): This whole method is a mess but needed to get stuff working for now
|
// TODO(sudden6): This whole method is a mess but needed to get stuff working for now
|
||||||
void CoreFile::handleAvatarOffer(uint32_t friendId, uint32_t fileId, bool accept)
|
void CoreFile::handleAvatarOffer(uint32_t friendId, uint32_t fileId, bool accept)
|
||||||
{
|
{
|
||||||
// TODO(sudden6): evil evil evil
|
|
||||||
auto core = Core::getInstance();
|
|
||||||
if (!accept) {
|
if (!accept) {
|
||||||
// If it's an avatar but we already have it cached, cancel
|
// If it's an avatar but we already have it cached, cancel
|
||||||
qDebug() << QString("Received avatar request %1:%2, reject, since we have it in cache.")
|
qDebug() << QString("Received avatar request %1:%2, reject, since we have it in cache.")
|
||||||
.arg(friendId)
|
.arg(friendId)
|
||||||
.arg(fileId);
|
.arg(fileId);
|
||||||
tox_file_control(core->tox.get(), friendId, fileId, TOX_FILE_CONTROL_CANCEL, nullptr);
|
tox_file_control(tox, friendId, fileId, TOX_FILE_CONTROL_CANCEL, nullptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,21 +375,23 @@ void CoreFile::handleAvatarOffer(uint32_t friendId, uint32_t fileId, bool accept
|
||||||
"in cache.")
|
"in cache.")
|
||||||
.arg(friendId)
|
.arg(friendId)
|
||||||
.arg(fileId);
|
.arg(fileId);
|
||||||
tox_file_control(core->tox.get(), friendId, fileId, TOX_FILE_CONTROL_RESUME, nullptr);
|
tox_file_control(tox, friendId, fileId, TOX_FILE_CONTROL_RESUME, nullptr);
|
||||||
|
|
||||||
ToxFile file{fileId, friendId, "<avatar>", "", ToxFile::RECEIVING};
|
ToxFile file{fileId, friendId, "<avatar>", "", ToxFile::RECEIVING};
|
||||||
file.filesize = 0;
|
file.filesize = 0;
|
||||||
file.fileKind = TOX_FILE_KIND_AVATAR;
|
file.fileKind = TOX_FILE_KIND_AVATAR;
|
||||||
file.resumeFileId.resize(TOX_FILE_ID_LENGTH);
|
file.resumeFileId.resize(TOX_FILE_ID_LENGTH);
|
||||||
tox_file_get_file_id(core->tox.get(), friendId, fileId, (uint8_t*)file.resumeFileId.data(),
|
tox_file_get_file_id(tox, friendId, fileId, (uint8_t*)file.resumeFileId.data(),
|
||||||
nullptr);
|
nullptr);
|
||||||
addFile(friendId, fileId, file);
|
addFile(friendId, fileId, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFile::onFileControlCallback(Tox*, uint32_t friendId, uint32_t fileId,
|
void CoreFile::onFileControlCallback(Tox*, uint32_t friendId, uint32_t fileId,
|
||||||
Tox_File_Control control, void* core)
|
Tox_File_Control control, void* vCore)
|
||||||
{
|
{
|
||||||
ToxFile* file = findFile(friendId, fileId);
|
Core* core = static_cast<Core*>(vCore);
|
||||||
|
CoreFile* coreFile = core->getCoreFile();
|
||||||
|
ToxFile* file = coreFile->findFile(friendId, fileId);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
qWarning("onFileControlCallback: No such file in queue");
|
qWarning("onFileControlCallback: No such file in queue");
|
||||||
return;
|
return;
|
||||||
|
@ -366,13 +401,13 @@ void CoreFile::onFileControlCallback(Tox*, uint32_t friendId, uint32_t fileId,
|
||||||
if (file->fileKind != TOX_FILE_KIND_AVATAR)
|
if (file->fileKind != TOX_FILE_KIND_AVATAR)
|
||||||
qDebug() << "File tranfer" << friendId << ":" << fileId << "cancelled by friend";
|
qDebug() << "File tranfer" << friendId << ":" << fileId << "cancelled by friend";
|
||||||
file->status = ToxFile::CANCELED;
|
file->status = ToxFile::CANCELED;
|
||||||
emit static_cast<Core*>(core)->fileTransferCancelled(*file);
|
emit coreFile->fileTransferCancelled(*file);
|
||||||
removeFile(friendId, fileId);
|
coreFile->removeFile(friendId, fileId);
|
||||||
} else if (control == TOX_FILE_CONTROL_PAUSE) {
|
} else if (control == TOX_FILE_CONTROL_PAUSE) {
|
||||||
qDebug() << "onFileControlCallback: Received pause for file " << friendId << ":" << fileId;
|
qDebug() << "onFileControlCallback: Received pause for file " << friendId << ":" << fileId;
|
||||||
file->pauseStatus.remotePause();
|
file->pauseStatus.remotePause();
|
||||||
file->status = ToxFile::PAUSED;
|
file->status = ToxFile::PAUSED;
|
||||||
emit static_cast<Core*>(core)->fileTransferRemotePausedUnpaused(*file, true);
|
emit coreFile->fileTransferRemotePausedUnpaused(*file, true);
|
||||||
} else if (control == TOX_FILE_CONTROL_RESUME) {
|
} else if (control == TOX_FILE_CONTROL_RESUME) {
|
||||||
if (file->direction == ToxFile::SENDING && file->fileKind == TOX_FILE_KIND_AVATAR)
|
if (file->direction == ToxFile::SENDING && file->fileKind == TOX_FILE_KIND_AVATAR)
|
||||||
qDebug() << "Avatar transfer" << fileId << "to friend" << friendId << "accepted";
|
qDebug() << "Avatar transfer" << fileId << "to friend" << friendId << "accepted";
|
||||||
|
@ -380,17 +415,19 @@ void CoreFile::onFileControlCallback(Tox*, uint32_t friendId, uint32_t fileId,
|
||||||
qDebug() << "onFileControlCallback: Received resume for file " << friendId << ":" << fileId;
|
qDebug() << "onFileControlCallback: Received resume for file " << friendId << ":" << fileId;
|
||||||
file->pauseStatus.remoteResume();
|
file->pauseStatus.remoteResume();
|
||||||
file->status = file->pauseStatus.paused() ? ToxFile::PAUSED : ToxFile::TRANSMITTING;
|
file->status = file->pauseStatus.paused() ? ToxFile::PAUSED : ToxFile::TRANSMITTING;
|
||||||
emit static_cast<Core*>(core)->fileTransferRemotePausedUnpaused(*file, false);
|
emit coreFile->fileTransferRemotePausedUnpaused(*file, false);
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Unhandled file control " << control << " for file " << friendId << ':' << fileId;
|
qWarning() << "Unhandled file control " << control << " for file " << friendId << ':' << fileId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFile::onFileDataCallback(Tox* tox, uint32_t friendId, uint32_t fileId, uint64_t pos,
|
void CoreFile::onFileDataCallback(Tox* tox, uint32_t friendId, uint32_t fileId, uint64_t pos,
|
||||||
size_t length, void* core)
|
size_t length, void* vCore)
|
||||||
{
|
{
|
||||||
|
|
||||||
ToxFile* file = findFile(friendId, fileId);
|
Core* core = static_cast<Core*>(vCore);
|
||||||
|
CoreFile* coreFile = core->getCoreFile();
|
||||||
|
ToxFile* file = coreFile->findFile(friendId, fileId);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
qWarning("onFileDataCallback: No such file in queue");
|
qWarning("onFileDataCallback: No such file in queue");
|
||||||
return;
|
return;
|
||||||
|
@ -400,14 +437,14 @@ void CoreFile::onFileDataCallback(Tox* tox, uint32_t friendId, uint32_t fileId,
|
||||||
if (!length) {
|
if (!length) {
|
||||||
file->status = ToxFile::FINISHED;
|
file->status = ToxFile::FINISHED;
|
||||||
if (file->fileKind != TOX_FILE_KIND_AVATAR) {
|
if (file->fileKind != TOX_FILE_KIND_AVATAR) {
|
||||||
emit static_cast<Core*>(core)->fileTransferFinished(*file);
|
emit coreFile->fileTransferFinished(*file);
|
||||||
emit static_cast<Core*>(core)->fileUploadFinished(file->filePath);
|
emit coreFile->fileUploadFinished(file->filePath);
|
||||||
}
|
}
|
||||||
removeFile(friendId, fileId);
|
coreFile->removeFile(friendId, fileId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr<uint8_t[]> data(new uint8_t[length]);
|
std::unique_ptr<uint8_t[]> data(new uint8_t[length]);
|
||||||
int64_t nread;
|
int64_t nread;
|
||||||
|
|
||||||
if (file->fileKind == TOX_FILE_KIND_AVATAR) {
|
if (file->fileKind == TOX_FILE_KIND_AVATAR) {
|
||||||
|
@ -420,9 +457,9 @@ void CoreFile::onFileDataCallback(Tox* tox, uint32_t friendId, uint32_t fileId,
|
||||||
if (nread <= 0) {
|
if (nread <= 0) {
|
||||||
qWarning("onFileDataCallback: Failed to read from file");
|
qWarning("onFileDataCallback: Failed to read from file");
|
||||||
file->status = ToxFile::CANCELED;
|
file->status = ToxFile::CANCELED;
|
||||||
emit static_cast<Core*>(core)->fileTransferCancelled(*file);
|
emit coreFile->fileTransferCancelled(*file);
|
||||||
tox_file_send_chunk(tox, friendId, fileId, pos, nullptr, 0, nullptr);
|
tox_file_send_chunk(tox, friendId, fileId, pos, nullptr, 0, nullptr);
|
||||||
removeFile(friendId, fileId);
|
coreFile->removeFile(friendId, fileId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
file->bytesSent += length;
|
file->bytesSent += length;
|
||||||
|
@ -433,15 +470,17 @@ void CoreFile::onFileDataCallback(Tox* tox, uint32_t friendId, uint32_t fileId,
|
||||||
qWarning("onFileDataCallback: Failed to send data chunk");
|
qWarning("onFileDataCallback: Failed to send data chunk");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (file->fileKind != TOX_FILE_KIND_AVATAR)
|
if (file->fileKind != TOX_FILE_KIND_AVATAR) {
|
||||||
emit static_cast<Core*>(core)->fileTransferInfo(*file);
|
emit coreFile->fileTransferInfo(*file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFile::onFileRecvChunkCallback(Tox* tox, uint32_t friendId, uint32_t fileId, uint64_t position,
|
void CoreFile::onFileRecvChunkCallback(Tox* tox, uint32_t friendId, uint32_t fileId, uint64_t position,
|
||||||
const uint8_t* data, size_t length, void* vCore)
|
const uint8_t* data, size_t length, void* vCore)
|
||||||
{
|
{
|
||||||
Core* core = static_cast<Core*>(vCore);
|
Core* core = static_cast<Core*>(vCore);
|
||||||
ToxFile* file = findFile(friendId, fileId);
|
CoreFile* coreFile = core->getCoreFile();
|
||||||
|
ToxFile* file = coreFile->findFile(friendId, fileId);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
qWarning("onFileRecvChunkCallback: No such file in queue");
|
qWarning("onFileRecvChunkCallback: No such file in queue");
|
||||||
tox_file_control(tox, friendId, fileId, TOX_FILE_CONTROL_CANCEL, nullptr);
|
tox_file_control(tox, friendId, fileId, TOX_FILE_CONTROL_CANCEL, nullptr);
|
||||||
|
@ -452,10 +491,10 @@ void CoreFile::onFileRecvChunkCallback(Tox* tox, uint32_t friendId, uint32_t fil
|
||||||
qWarning("onFileRecvChunkCallback: Received a chunk out-of-order, aborting transfer");
|
qWarning("onFileRecvChunkCallback: Received a chunk out-of-order, aborting transfer");
|
||||||
if (file->fileKind != TOX_FILE_KIND_AVATAR) {
|
if (file->fileKind != TOX_FILE_KIND_AVATAR) {
|
||||||
file->status = ToxFile::CANCELED;
|
file->status = ToxFile::CANCELED;
|
||||||
emit core->fileTransferCancelled(*file);
|
emit coreFile->fileTransferCancelled(*file);
|
||||||
}
|
}
|
||||||
tox_file_control(tox, friendId, fileId, TOX_FILE_CONTROL_CANCEL, nullptr);
|
tox_file_control(tox, friendId, fileId, TOX_FILE_CONTROL_CANCEL, nullptr);
|
||||||
removeFile(friendId, fileId);
|
coreFile->removeFile(friendId, fileId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,26 +508,29 @@ void CoreFile::onFileRecvChunkCallback(Tox* tox, uint32_t friendId, uint32_t fil
|
||||||
emit core->friendAvatarChanged(core->getFriendPublicKey(friendId), file->avatarData);
|
emit core->friendAvatarChanged(core->getFriendPublicKey(friendId), file->avatarData);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
emit core->fileTransferFinished(*file);
|
emit coreFile->fileTransferFinished(*file);
|
||||||
emit core->fileDownloadFinished(file->filePath);
|
emit coreFile->fileDownloadFinished(file->filePath);
|
||||||
}
|
}
|
||||||
removeFile(friendId, fileId);
|
coreFile->removeFile(friendId, fileId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file->fileKind == TOX_FILE_KIND_AVATAR)
|
if (file->fileKind == TOX_FILE_KIND_AVATAR) {
|
||||||
file->avatarData.append((char*)data, length);
|
file->avatarData.append((char*)data, length);
|
||||||
else
|
} else {
|
||||||
file->file->write((char*)data, length);
|
file->file->write((char*)data, length);
|
||||||
|
}
|
||||||
file->bytesSent += length;
|
file->bytesSent += length;
|
||||||
file->hashGenerator->addData((const char*)data, length);
|
file->hashGenerator->addData((const char*)data, length);
|
||||||
|
|
||||||
if (file->fileKind != TOX_FILE_KIND_AVATAR)
|
if (file->fileKind != TOX_FILE_KIND_AVATAR) {
|
||||||
emit static_cast<Core*>(core)->fileTransferInfo(*file);
|
emit coreFile->fileTransferInfo(*file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreFile::onConnectionStatusChanged(Core* core, uint32_t friendId, bool online)
|
void CoreFile::onConnectionStatusChanged(uint32_t friendId, Status state)
|
||||||
{
|
{
|
||||||
|
bool isOffline = state == Status::Offline;
|
||||||
// TODO: Actually resume broken file transfers
|
// TODO: Actually resume broken file transfers
|
||||||
// We need to:
|
// We need to:
|
||||||
// - Start a new file transfer with the same 32byte file ID with toxcore
|
// - Start a new file transfer with the same 32byte file ID with toxcore
|
||||||
|
@ -496,11 +538,11 @@ void CoreFile::onConnectionStatusChanged(Core* core, uint32_t friendId, bool onl
|
||||||
// - Update the fileNum in our ToxFile
|
// - 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
|
// - Update the users of our signals to check the 32byte tox file ID, not the uint32_t file_num
|
||||||
// (fileId)
|
// (fileId)
|
||||||
ToxFile::FileStatus status = online ? ToxFile::TRANSMITTING : ToxFile::BROKEN;
|
ToxFile::FileStatus status = !isOffline ? ToxFile::TRANSMITTING : ToxFile::BROKEN;
|
||||||
for (uint64_t key : fileMap.keys()) {
|
for (uint64_t key : fileMap.keys()) {
|
||||||
if (key >> 32 != friendId)
|
if (key >> 32 != friendId)
|
||||||
continue;
|
continue;
|
||||||
fileMap[key].status = status;
|
fileMap[key].status = status;
|
||||||
emit core->fileTransferBrokenUnbroken(fileMap[key], !online);
|
emit fileTransferBrokenUnbroken(fileMap[key], !isOffline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,60 +27,85 @@
|
||||||
#include <tox/tox.h>
|
#include <tox/tox.h>
|
||||||
|
|
||||||
#include "toxfile.h"
|
#include "toxfile.h"
|
||||||
|
#include "src/core/core.h"
|
||||||
|
#include "src/core/toxpk.h"
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
struct Tox;
|
struct Tox;
|
||||||
class Core;
|
class CoreFile;
|
||||||
|
|
||||||
class CoreFile
|
using CoreFilePtr = std::unique_ptr<CoreFile>;
|
||||||
|
|
||||||
|
class CoreFile : public QObject
|
||||||
{
|
{
|
||||||
friend class Core;
|
Q_OBJECT
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void handleAvatarOffer(uint32_t friendId, uint32_t fileId, bool accept);
|
void handleAvatarOffer(uint32_t friendId, uint32_t fileId, bool accept);
|
||||||
|
static CoreFilePtr makeCoreFile(Core* core, Tox* tox, QMutex& coreLoopLock);
|
||||||
|
|
||||||
private:
|
void sendFile(uint32_t friendId, QString filename, QString filePath,
|
||||||
CoreFile() = delete;
|
|
||||||
|
|
||||||
// Internal file sending APIs, used by Core. Public API in core.h
|
|
||||||
private:
|
|
||||||
static void sendFile(Core* core, uint32_t friendId, QString filename, QString filePath,
|
|
||||||
long long filesize);
|
long long filesize);
|
||||||
static void sendAvatarFile(Core* core, uint32_t friendId, const QByteArray& data);
|
void sendAvatarFile(uint32_t friendId, const QByteArray& data);
|
||||||
static void pauseResumeFile(Core* core, uint32_t friendId, uint32_t fileId);
|
void pauseResumeFile(uint32_t friendId, uint32_t fileId);
|
||||||
static void cancelFileSend(Core* core, uint32_t friendId, uint32_t fileId);
|
void cancelFileSend(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);
|
void cancelFileRecv(uint32_t friendId, uint32_t fileId);
|
||||||
static void acceptFileRecvRequest(Core* core, uint32_t friendId, uint32_t fileId, QString path);
|
void rejectFileRecvRequest(uint32_t friendId, uint32_t fileId);
|
||||||
static ToxFile* findFile(uint32_t friendId, uint32_t fileId);
|
void acceptFileRecvRequest(uint32_t friendId, uint32_t fileId, QString path);
|
||||||
static void addFile(uint32_t friendId, uint32_t fileId, const ToxFile& file);
|
|
||||||
static void removeFile(uint32_t friendId, uint32_t fileId);
|
unsigned corefileIterationInterval();
|
||||||
static unsigned corefileIterationInterval();
|
|
||||||
|
signals:
|
||||||
|
void fileSendStarted(ToxFile file);
|
||||||
|
void fileReceiveRequested(ToxFile file);
|
||||||
|
void fileTransferAccepted(ToxFile file);
|
||||||
|
void fileTransferCancelled(ToxFile file);
|
||||||
|
void fileTransferFinished(ToxFile file);
|
||||||
|
void fileUploadFinished(const QString& path);
|
||||||
|
void fileDownloadFinished(const QString& path);
|
||||||
|
void fileTransferPaused(ToxFile file);
|
||||||
|
void fileTransferInfo(ToxFile file);
|
||||||
|
void fileTransferRemotePausedUnpaused(ToxFile file, bool paused);
|
||||||
|
void fileTransferBrokenUnbroken(ToxFile file, bool broken);
|
||||||
|
void fileNameChanged(const ToxPk& friendPk);
|
||||||
|
void fileSendFailed(uint32_t friendId, const QString& fname);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CoreFile(Tox* core, QMutex& coreLoopLock);
|
||||||
|
|
||||||
|
ToxFile* findFile(uint32_t friendId, uint32_t fileId);
|
||||||
|
void addFile(uint32_t friendId, uint32_t fileId, const ToxFile& file);
|
||||||
|
void removeFile(uint32_t friendId, uint32_t fileId);
|
||||||
static constexpr uint64_t getFriendKey(uint32_t friendId, uint32_t fileId)
|
static constexpr uint64_t getFriendKey(uint32_t friendId, uint32_t fileId)
|
||||||
{
|
{
|
||||||
return (static_cast<std::uint64_t>(friendId) << 32) + fileId;
|
return (static_cast<std::uint64_t>(friendId) << 32) + fileId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
static void connectCallbacks(Tox& tox);
|
||||||
static void onFileReceiveCallback(Tox*, uint32_t friendId, uint32_t fileId, uint32_t kind,
|
static void onFileReceiveCallback(Tox* tox, uint32_t friendId, uint32_t fileId, uint32_t kind,
|
||||||
uint64_t filesize, const uint8_t* fname, size_t fnameLen,
|
uint64_t filesize, const uint8_t* fname, size_t fnameLen,
|
||||||
void* vCore);
|
void* vCore);
|
||||||
static void onFileControlCallback(Tox* tox, uint32_t friendId, uint32_t fileId,
|
static void onFileControlCallback(Tox* tox, uint32_t friendId, uint32_t fileId,
|
||||||
Tox_File_Control control, void* core);
|
Tox_File_Control control, void* vCore);
|
||||||
static void onFileDataCallback(Tox* tox, uint32_t friendId, uint32_t fileId, uint64_t pos,
|
static void onFileDataCallback(Tox* tox, uint32_t friendId, uint32_t fileId, uint64_t pos,
|
||||||
size_t length, void* core);
|
size_t length, void* vCore);
|
||||||
static void onFileRecvChunkCallback(Tox* tox, uint32_t friendId, uint32_t fileId, uint64_t position,
|
static void onFileRecvChunkCallback(Tox* tox, uint32_t friendId, uint32_t fileId, uint64_t position,
|
||||||
const uint8_t* data, size_t length, void* vCore);
|
const uint8_t* data, size_t length, void* vCore);
|
||||||
static void onConnectionStatusChanged(Core* core, uint32_t friendId, bool online);
|
|
||||||
|
static QString getCleanFileName(QString filename);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onConnectionStatusChanged(uint32_t friendId, Status state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static QMutex fileSendMutex;
|
QHash<uint64_t, ToxFile> fileMap;
|
||||||
static QHash<uint64_t, ToxFile> fileMap;
|
Tox* tox;
|
||||||
static QString getCleanFileName(QString filename);
|
QMutex* coreLoopLock = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // COREFILE_H
|
#endif // COREFILE_H
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "avatarbroadcaster.h"
|
#include "avatarbroadcaster.h"
|
||||||
#include "src/core/core.h"
|
#include "src/core/core.h"
|
||||||
|
#include "src/core/corefile.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
@ -66,7 +67,8 @@ void AvatarBroadcaster::sendAvatarTo(uint32_t friendId)
|
||||||
return;
|
return;
|
||||||
if (!Core::getInstance()->isFriendOnline(friendId))
|
if (!Core::getInstance()->isFriendOnline(friendId))
|
||||||
return;
|
return;
|
||||||
Core::getInstance()->sendAvatarFile(friendId, avatarData);
|
CoreFile* coreFile = Core::getInstance()->getCoreFile();
|
||||||
|
coreFile->sendAvatarFile(friendId, avatarData);
|
||||||
friendsSentTo[friendId] = true;
|
friendsSentTo[friendId] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -333,7 +333,7 @@ void Profile::onAvatarOfferReceived(uint32_t friendId, uint32_t fileId, const QB
|
||||||
{
|
{
|
||||||
// accept if we don't have it already
|
// accept if we don't have it already
|
||||||
const bool accept = getAvatarHash(core->getFriendPublicKey(friendId)) != avatarHash;
|
const bool accept = getAvatarHash(core->getFriendPublicKey(friendId)) != avatarHash;
|
||||||
CoreFile::handleAvatarOffer(friendId, fileId, accept);
|
core->getCoreFile()->handleAvatarOffer(friendId, fileId, accept);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "src/chatlog/content/text.h"
|
#include "src/chatlog/content/text.h"
|
||||||
#include "src/core/core.h"
|
#include "src/core/core.h"
|
||||||
#include "src/core/coreav.h"
|
#include "src/core/coreav.h"
|
||||||
|
#include "src/core/corefile.h"
|
||||||
#include "src/model/friend.h"
|
#include "src/model/friend.h"
|
||||||
#include "src/nexus.h"
|
#include "src/nexus.h"
|
||||||
#include "src/persistence/history.h"
|
#include "src/persistence/history.h"
|
||||||
|
@ -160,18 +161,19 @@ ChatForm::ChatForm(Friend* chatFriend, History* history)
|
||||||
|
|
||||||
const Core* core = Core::getInstance();
|
const Core* core = Core::getInstance();
|
||||||
const Profile* profile = Nexus::getProfile();
|
const Profile* profile = Nexus::getProfile();
|
||||||
connect(core, &Core::fileReceiveRequested, this, &ChatForm::onFileRecvRequest);
|
const CoreFile* coreFile = core->getCoreFile();
|
||||||
|
connect(coreFile, &CoreFile::fileReceiveRequested, this, &ChatForm::onFileRecvRequest);
|
||||||
connect(profile, &Profile::friendAvatarChanged, this, &ChatForm::onAvatarChanged);
|
connect(profile, &Profile::friendAvatarChanged, this, &ChatForm::onAvatarChanged);
|
||||||
connect(core, &Core::fileSendStarted, this, &ChatForm::startFileSend);
|
connect(coreFile, &CoreFile::fileSendStarted, this, &ChatForm::startFileSend);
|
||||||
connect(core, &Core::fileTransferFinished, this, &ChatForm::onFileTransferFinished);
|
connect(coreFile, &CoreFile::fileTransferFinished, this, &ChatForm::onFileTransferFinished);
|
||||||
connect(core, &Core::fileTransferCancelled, this, &ChatForm::onFileTransferCancelled);
|
connect(coreFile, &CoreFile::fileTransferCancelled, this, &ChatForm::onFileTransferCancelled);
|
||||||
connect(core, &Core::fileTransferBrokenUnbroken, this, &ChatForm::onFileTransferBrokenUnbroken);
|
connect(coreFile, &CoreFile::fileTransferBrokenUnbroken, this, &ChatForm::onFileTransferBrokenUnbroken);
|
||||||
connect(core, &Core::fileSendFailed, this, &ChatForm::onFileSendFailed);
|
connect(coreFile, &CoreFile::fileSendFailed, this, &ChatForm::onFileSendFailed);
|
||||||
connect(core, &Core::receiptRecieved, this, &ChatForm::onReceiptReceived);
|
connect(core, &Core::receiptRecieved, this, &ChatForm::onReceiptReceived);
|
||||||
connect(core, &Core::friendMessageReceived, this, &ChatForm::onFriendMessageReceived);
|
connect(core, &Core::friendMessageReceived, this, &ChatForm::onFriendMessageReceived);
|
||||||
connect(core, &Core::friendTypingChanged, this, &ChatForm::onFriendTypingChanged);
|
connect(core, &Core::friendTypingChanged, this, &ChatForm::onFriendTypingChanged);
|
||||||
connect(core, &Core::friendStatusChanged, this, &ChatForm::onFriendStatusChanged);
|
connect(core, &Core::friendStatusChanged, this, &ChatForm::onFriendStatusChanged);
|
||||||
connect(core, &Core::fileNameChanged, this, &ChatForm::onFileNameChanged);
|
connect(coreFile, &CoreFile::fileNameChanged, this, &ChatForm::onFileNameChanged);
|
||||||
|
|
||||||
|
|
||||||
const CoreAV* av = core->getAv();
|
const CoreAV* av = core->getAv();
|
||||||
|
@ -297,7 +299,7 @@ void ChatForm::onAttachClicked()
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 filesize = file.size();
|
qint64 filesize = file.size();
|
||||||
core->sendFile(f->getId(), fileName, path, filesize);
|
core->getCoreFile()->sendFile(f->getId(), fileName, path, filesize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -762,7 +764,7 @@ void ChatForm::dropEvent(QDropEvent* ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.exists()) {
|
if (info.exists()) {
|
||||||
core->sendFile(f->getId(), fileName, info.absoluteFilePath(), info.size());
|
core->getCoreFile()->sendFile(f->getId(), fileName, info.absoluteFilePath(), info.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -984,7 +986,8 @@ void ChatForm::sendImage(const QPixmap& pixmap)
|
||||||
qint64 filesize = file.size();
|
qint64 filesize = file.size();
|
||||||
file.close();
|
file.close();
|
||||||
QFileInfo fi(file);
|
QFileInfo fi(file);
|
||||||
Core::getInstance()->sendFile(f->getId(), fi.fileName(), fi.filePath(), filesize);
|
CoreFile* coreFile = Core::getInstance()->getCoreFile();
|
||||||
|
coreFile->sendFile(f->getId(), fi.fileName(), fi.filePath(), filesize);
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::warning(this,
|
QMessageBox::warning(this,
|
||||||
tr("Failed to open temporary file", "Temporary file for screenshot"),
|
tr("Failed to open temporary file", "Temporary file for screenshot"),
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#include "src/audio/audio.h"
|
#include "src/audio/audio.h"
|
||||||
#include "src/core/core.h"
|
#include "src/core/core.h"
|
||||||
#include "src/core/coreav.h"
|
#include "src/core/coreav.h"
|
||||||
|
#include "src/core/corefile.h"
|
||||||
#include "src/model/chatroom/friendchatroom.h"
|
#include "src/model/chatroom/friendchatroom.h"
|
||||||
#include "src/model/chatroom/groupchatroom.h"
|
#include "src/model/chatroom/groupchatroom.h"
|
||||||
#include "src/model/friend.h"
|
#include "src/model/friend.h"
|
||||||
|
@ -234,6 +235,7 @@ void Widget::init()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Core* core = Nexus::getCore();
|
Core* core = Nexus::getCore();
|
||||||
|
CoreFile* coreFile = core->getCoreFile();
|
||||||
Profile* profile = Nexus::getProfile();
|
Profile* profile = Nexus::getProfile();
|
||||||
profileInfo = new ProfileInfo(core, profile);
|
profileInfo = new ProfileInfo(core, profile);
|
||||||
profileForm = new ProfileForm(profileInfo);
|
profileForm = new ProfileForm(profileInfo);
|
||||||
|
@ -243,8 +245,8 @@ void Widget::init()
|
||||||
|
|
||||||
connect(profile, &Profile::selfAvatarChanged, profileForm, &ProfileForm::onSelfAvatarLoaded);
|
connect(profile, &Profile::selfAvatarChanged, profileForm, &ProfileForm::onSelfAvatarLoaded);
|
||||||
|
|
||||||
connect(core, &Core::fileDownloadFinished, filesForm, &FilesForm::onFileDownloadComplete);
|
connect(coreFile, &CoreFile::fileDownloadFinished, filesForm, &FilesForm::onFileDownloadComplete);
|
||||||
connect(core, &Core::fileUploadFinished, filesForm, &FilesForm::onFileUploadComplete);
|
connect(coreFile, &CoreFile::fileUploadFinished, filesForm, &FilesForm::onFileUploadComplete);
|
||||||
connect(ui->addButton, &QPushButton::clicked, this, &Widget::onAddClicked);
|
connect(ui->addButton, &QPushButton::clicked, this, &Widget::onAddClicked);
|
||||||
connect(ui->groupButton, &QPushButton::clicked, this, &Widget::onGroupClicked);
|
connect(ui->groupButton, &QPushButton::clicked, this, &Widget::onGroupClicked);
|
||||||
connect(ui->transferButton, &QPushButton::clicked, this, &Widget::onTransferClicked);
|
connect(ui->transferButton, &QPushButton::clicked, this, &Widget::onTransferClicked);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user