diff --git a/core.cpp b/core.cpp index 1b3eb4fc4..ad0d943a3 100644 --- a/core.cpp +++ b/core.cpp @@ -291,6 +291,33 @@ void Core::onConnectionStatusChanged(Tox*/* tox*/, int friendId, uint8_t status, emit static_cast(core)->friendStatusChanged(friendId, friendStatus); if (friendStatus == Status::Offline) { static_cast(core)->checkLastOnline(friendId); + + for (ToxFile& f : fileSendQueue) + { + if (f.friendId == friendId && f.status == ToxFile::TRANSMITTING) + { + f.status = ToxFile::BROKEN; + emit static_cast(core)->fileTransferBrokenUnbroken(f, true); + } + } + for (ToxFile& f : fileRecvQueue) + { + if (f.friendId == friendId && f.status == ToxFile::TRANSMITTING) + { + f.status = ToxFile::BROKEN; + emit static_cast(core)->fileTransferBrokenUnbroken(f, true); + } + } + } else { + for (ToxFile& f : fileRecvQueue) + { + if (f.friendId == friendId && f.status == ToxFile::BROKEN) + { + qDebug() << QString("Core::onConnectionStatusChanged: %1: resuming broken filetransfer from position: %2").arg(f.file->fileName()).arg(f.bytesSent); + tox_file_send_control(static_cast(core)->tox, friendId, 1, f.fileNum, TOX_FILECONTROL_RESUME_BROKEN, reinterpret_cast(&f.bytesSent), sizeof(uint64_t)); + emit static_cast(core)->fileTransferBrokenUnbroken(f, false); + } + } } } @@ -328,7 +355,7 @@ void Core::onFileSendRequestCallback(Tox*, int32_t friendnumber, uint8_t filenum emit static_cast(core)->fileReceiveRequested(fileRecvQueue.last()); } void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber, - uint8_t control_type, const uint8_t*, uint16_t, void *core) + uint8_t control_type, const uint8_t* data, uint16_t length, void *core) { ToxFile* file{nullptr}; if (receive_send == 1) @@ -415,12 +442,39 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive } else if (receive_send == 0 && control_type == TOX_FILECONTROL_ACCEPT) { + if (file->status == ToxFile::BROKEN) + { + emit static_cast(core)->fileTransferBrokenUnbroken(*file, false); + file->status = ToxFile::TRANSMITTING; + } emit static_cast(core)->fileTransferRemotePausedUnpaused(*file, false); } else if ((receive_send == 0 || receive_send == 1) && control_type == TOX_FILECONTROL_PAUSE) { emit static_cast(core)->fileTransferRemotePausedUnpaused(*file, true); } + else if (receive_send == 1 && control_type == TOX_FILECONTROL_RESUME_BROKEN) + { + if (length != sizeof(uint64_t)) + return; + + qDebug() << "Core::onFileControlCallback: TOX_FILECONTROL_RESUME_BROKEN"; + + uint64_t resumePos = *reinterpret_cast(data); + + if (resumePos >= file->filesize) + { + qWarning() << "Core::onFileControlCallback: invalid resume position"; + tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); // don't sure about it + return; + } + + file->status = ToxFile::TRANSMITTING; + emit static_cast(core)->fileTransferBrokenUnbroken(*file, false); + + file->bytesSent = resumePos; + tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_ACCEPT, nullptr, 0); + } else { qDebug() << QString("Core: File control callback, receive_send=%1, control_type=%2") @@ -640,7 +694,7 @@ void Core::pauseResumeFileRecv(int friendId, int fileNum) tox_file_send_control(tox, file->friendId, 1, file->fileNum, TOX_FILECONTROL_ACCEPT, nullptr, 0); } else - qWarning() << "Core::pauseResumeFileRecv: File is stopped"; + qWarning() << "Core::pauseResumeFileRecv: File is stopped or broken"; } void Core::cancelFileSend(int friendId, int fileNum) diff --git a/core.h b/core.h index b1425c59e..fbaca60da 100644 --- a/core.h +++ b/core.h @@ -150,6 +150,7 @@ signals: void fileTransferPaused(int FriendId, int FileNum, ToxFile::FileDirection direction); void fileTransferInfo(int FriendId, int FileNum, int64_t Filesize, int64_t BytesSent, ToxFile::FileDirection direction); void fileTransferRemotePausedUnpaused(ToxFile file, bool paused); + void fileTransferBrokenUnbroken(ToxFile file, bool broken); void fileSendFailed(int FriendId, const QString& fname); diff --git a/corestructs.h b/corestructs.h index a2bb6f31f..00da8a6a5 100644 --- a/corestructs.h +++ b/corestructs.h @@ -50,7 +50,8 @@ struct ToxFile { STOPPED, PAUSED, - TRANSMITTING + TRANSMITTING, + BROKEN }; enum FileDirection : bool diff --git a/filetransferinstance.cpp b/filetransferinstance.cpp index f8b10ecc8..75ab36d3e 100644 --- a/filetransferinstance.cpp +++ b/filetransferinstance.cpp @@ -24,6 +24,7 @@ #include #define CONTENT_WIDTH 250 +#define MAX_PREVIEW_SIZE 25*1024*1024 uint FileTransferInstance::Idconter = 0; @@ -44,13 +45,17 @@ FileTransferInstance::FileTransferInstance(ToxFile File) size = getHumanReadableSize(File.filesize); speed = "0B/s"; eta = "00:00"; + if (File.direction == ToxFile::SENDING) { - QImage preview; - File.file->seek(0); - if (preview.loadFromData(File.file->readAll())) + if (File.file->size() <= MAX_PREVIEW_SIZE) { - pic = preview.scaledToHeight(50); + QImage preview; + File.file->seek(0); + if (preview.loadFromData(File.file->readAll())) + { + pic = preview.scaledToHeight(50); + } } File.file->seek(0); } @@ -116,7 +121,7 @@ void FileTransferInstance::onFileTransferFinished(ToxFile File) { QImage preview; QFile previewFile(File.filePath); - if (previewFile.open(QIODevice::ReadOnly) && previewFile.size() <= 1024*1024*25) // Don't preview big (>25MiB) images + if (previewFile.open(QIODevice::ReadOnly) && previewFile.size() <= MAX_PREVIEW_SIZE) // Don't preview big (>25MiB) images { if (preview.loadFromData(previewFile.readAll())) { @@ -286,6 +291,12 @@ QString FileTransferInstance::getHtmlImage() rightBtnImg = QImage(":/ui/fileTransferInstance/pauseGreyFileButton.png"); res = draw2ButtonsForm("silver", leftBtnImg, rightBtnImg); + } else if (state == tsBroken) + { + QImage leftBtnImg(":/ui/fileTransferInstance/stopFileButton.png"); + QImage rightBtnImg(":/ui/fileTransferInstance/pauseGreyFileButton.png"); + + res = draw2ButtonsForm("red", leftBtnImg, rightBtnImg); } else if (state == tsCanceled) { res = drawButtonlessForm("red"); @@ -411,3 +422,16 @@ QImage FileTransferInstance::drawProgressBarImg(const double &part, int w, int h return progressBar; } + +void FileTransferInstance::onFileTransferBrokenUnbroken(ToxFile File, bool broken) +{ + if (File.fileNum != fileNum || File.friendId != friendId || File.direction != direction) + return; + + if (broken) + state = tsBroken; + else + state = tsProcessing; + + emit stateUpdated(); +} diff --git a/filetransferinstance.h b/filetransferinstance.h index fb54fd8f6..c627fb3ee 100644 --- a/filetransferinstance.h +++ b/filetransferinstance.h @@ -28,7 +28,7 @@ class FileTransferInstance : public QObject { Q_OBJECT public: - enum TransfState {tsPending, tsProcessing, tsPaused, tsFinished, tsCanceled}; + enum TransfState {tsPending, tsProcessing, tsPaused, tsFinished, tsCanceled, tsBroken}; public: explicit FileTransferInstance(ToxFile File); @@ -43,6 +43,7 @@ public slots: void onFileTransferAccepted(ToxFile File); void onFileTransferPaused(int FriendId, int FileNum, ToxFile::FileDirection Direction); void onFileTransferRemotePausedUnpaused(ToxFile File, bool paused); + void onFileTransferBrokenUnbroken(ToxFile File, bool broken); void pressFromHtml(QString); signals: diff --git a/widget/form/chatform.cpp b/widget/form/chatform.cpp index 9c57f0d88..ed307bc89 100644 --- a/widget/form/chatform.cpp +++ b/widget/form/chatform.cpp @@ -119,6 +119,7 @@ void ChatForm::startFileSend(ToxFile file) connect(Core::getInstance(), SIGNAL(fileTransferAccepted(ToxFile)), fileTrans, SLOT(onFileTransferAccepted(ToxFile))); connect(Core::getInstance(), SIGNAL(fileTransferPaused(int,int,ToxFile::FileDirection)), fileTrans, SLOT(onFileTransferPaused(int,int,ToxFile::FileDirection))); connect(Core::getInstance(), SIGNAL(fileTransferRemotePausedUnpaused(ToxFile,bool)), fileTrans, SLOT(onFileTransferRemotePausedUnpaused(ToxFile,bool))); + connect(Core::getInstance(), SIGNAL(fileTransferBrokenUnbroken(ToxFile, bool)), fileTrans, SLOT(onFileTransferBrokenUnbroken(ToxFile, bool))); QString name = Widget::getInstance()->getUsername(); if (name == previousName) @@ -142,6 +143,7 @@ void ChatForm::onFileRecvRequest(ToxFile file) connect(Core::getInstance(), SIGNAL(fileTransferAccepted(ToxFile)), fileTrans, SLOT(onFileTransferAccepted(ToxFile))); connect(Core::getInstance(), SIGNAL(fileTransferPaused(int,int,ToxFile::FileDirection)), fileTrans, SLOT(onFileTransferPaused(int,int,ToxFile::FileDirection))); connect(Core::getInstance(), SIGNAL(fileTransferRemotePausedUnpaused(ToxFile,bool)), fileTrans, SLOT(onFileTransferRemotePausedUnpaused(ToxFile,bool))); + connect(Core::getInstance(), SIGNAL(fileTransferBrokenUnbroken(ToxFile, bool)), fileTrans, SLOT(onFileTransferBrokenUnbroken(ToxFile, bool))); Widget* w = Widget::getInstance(); if (!w->isFriendWidgetCurActiveWidget(f)|| w->getIsWindowMinimized() || !w->isActiveWindow())