diff --git a/CMakeLists.txt b/CMakeLists.txt index a229ad633..b5bdda9c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -249,6 +249,8 @@ set(${PROJECT_NAME}_SOURCES src/chatlog/documentcache.h src/chatlog/pixmapcache.cpp src/chatlog/pixmapcache.h + src/chatlog/toxfileprogress.cpp + src/chatlog/toxfileprogress.h src/chatlog/textformatter.cpp src/chatlog/textformatter.h src/core/coreav.cpp diff --git a/src/chatlog/content/filetransferwidget.cpp b/src/chatlog/content/filetransferwidget.cpp index 3da558b3c..db0428b51 100644 --- a/src/chatlog/content/filetransferwidget.cpp +++ b/src/chatlog/content/filetransferwidget.cpp @@ -41,6 +41,7 @@ #include + // The leftButton is used to accept, pause, or resume a file transfer, as well as to open a // received file. // The rightButton is used to cancel a file transfer, or to open the directory a file was @@ -50,7 +51,6 @@ FileTransferWidget::FileTransferWidget(QWidget* parent, ToxFile file) : QWidget(parent) , ui(new Ui::FileTransferWidget) , fileInfo(file) - , lastTick(QTime::currentTime()) , backgroundColor(Style::getColor(Style::LightGrey)) , buttonColor(Style::getColor(Style::Yellow)) , buttonBackgroundColor(Style::getColor(Style::White)) @@ -84,8 +84,6 @@ FileTransferWidget::FileTransferWidget(QWidget* parent, ToxFile file) update(); }); - setBackgroundColor(Style::getColor(Style::LightGrey), false); - connect(Core::getInstance(), &Core::fileTransferInfo, this, &FileTransferWidget::onFileTransferInfo); connect(Core::getInstance(), &Core::fileTransferAccepted, this, @@ -105,16 +103,11 @@ FileTransferWidget::FileTransferWidget(QWidget* parent, ToxFile file) connect(ui->previewButton, &QPushButton::clicked, this, &FileTransferWidget::onPreviewButtonClicked); - setupButtons(); + // Set lastStatus to anything but the file's current value, this forces an update + lastStatus = file.status == ToxFile::FINISHED ? ToxFile::INITIALIZING : ToxFile::FINISHED; + updateWidget(file); // preview - if (fileInfo.direction == ToxFile::SENDING) { - showPreview(fileInfo.filePath); - ui->progressLabel->setText(tr("Waiting to send...", "file transfer widget")); - } else { - ui->progressLabel->setText(tr("Accept to receive this file", "file transfer widget")); - } - setFixedHeight(64); } @@ -267,154 +260,32 @@ void FileTransferWidget::paintEvent(QPaintEvent*) void FileTransferWidget::onFileTransferInfo(ToxFile file) { - QTime now = QTime::currentTime(); - qint64 dt = lastTick.msecsTo(now); // ms - - if (fileInfo != file || dt < 1000) - return; - - fileInfo = file; - - if (fileInfo.status == ToxFile::TRANSMITTING) { - // update progress - qreal progress = static_cast(file.bytesSent) / static_cast(file.filesize); - ui->progressBar->setValue(static_cast(progress * 100.0)); - - // ETA, speed - qreal deltaSecs = dt / 1000.0; - - // (can't use ::abs or ::max on unsigned types substraction, they'd just overflow) - quint64 deltaBytes = file.bytesSent > lastBytesSent ? file.bytesSent - lastBytesSent - : lastBytesSent - file.bytesSent; - qreal bytesPerSec = static_cast(static_cast(deltaBytes) / deltaSecs); - - // calculate mean - meanIndex = meanIndex % TRANSFER_ROLLING_AVG_COUNT; - meanData[meanIndex++] = bytesPerSec; - - qreal meanBytesPerSec = 0.0; - for (size_t i = 0; i < TRANSFER_ROLLING_AVG_COUNT; ++i) - meanBytesPerSec += meanData[i]; - - meanBytesPerSec /= static_cast(TRANSFER_ROLLING_AVG_COUNT); - - // update UI - if (meanBytesPerSec > 0) { - // ETA - QTime toGo = QTime(0, 0).addSecs((file.filesize - file.bytesSent) / meanBytesPerSec); - QString format = toGo.hour() > 0 ? "hh:mm:ss" : "mm:ss"; - ui->etaLabel->setText(toGo.toString(format)); - } else { - ui->etaLabel->setText(""); - } - - ui->progressLabel->setText(getHumanReadableSize(meanBytesPerSec) + "/s"); - - lastBytesSent = file.bytesSent; - } - - lastTick = now; - - // trigger repaint - update(); + updateWidget(file); } void FileTransferWidget::onFileTransferAccepted(ToxFile file) { - if (fileInfo != file) - return; - - fileInfo = file; - - setBackgroundColor(Style::getColor(Style::LightGrey), false); - - setupButtons(); + updateWidget(file); } void FileTransferWidget::onFileTransferCancelled(ToxFile file) { - if (fileInfo != file) - return; - - fileInfo = file; - active = false; - - setBackgroundColor(Style::getColor(Style::Red), true); - - setupButtons(); - hideWidgets(); - - disconnect(Core::getInstance(), nullptr, this, nullptr); + updateWidget(file); } void FileTransferWidget::onFileTransferPaused(ToxFile file) { - if (fileInfo != file) - return; - - fileInfo = file; - - ui->etaLabel->setText(""); - ui->progressLabel->setText(tr("Paused", "file transfer widget")); - - // reset mean - meanIndex = 0; - for (size_t i = 0; i < TRANSFER_ROLLING_AVG_COUNT; ++i) - meanData[i] = 0.0; - - setBackgroundColor(Style::getColor(Style::LightGrey), false); - - setupButtons(); + updateWidget(file); } void FileTransferWidget::onFileTransferResumed(ToxFile file) { - if (fileInfo != file) - return; - - fileInfo = file; - - ui->etaLabel->setText(""); - ui->progressLabel->setText(tr("Resuming...", "file transfer widget")); - - // reset mean - meanIndex = 0; - for (size_t i = 0; i < TRANSFER_ROLLING_AVG_COUNT; ++i) - meanData[i] = 0.0; - - setBackgroundColor(Style::getColor(Style::LightGrey), false); - - setupButtons(); + updateWidget(file); } void FileTransferWidget::onFileTransferFinished(ToxFile file) { - if (fileInfo != file) - return; - - fileInfo = file; - active = false; - - setBackgroundColor(Style::getColor(Style::Green), true); - - setupButtons(); - hideWidgets(); - - ui->leftButton->setIcon(QIcon(Style::getImagePath("fileTransferInstance/yes.svg"))); - ui->leftButton->setObjectName("ok"); - ui->leftButton->setToolTip(tr("Open file")); - ui->leftButton->show(); - - ui->rightButton->setIcon(QIcon(Style::getImagePath("fileTransferInstance/dir.svg"))); - ui->rightButton->setObjectName("dir"); - ui->rightButton->setToolTip(tr("Open file directory")); - ui->rightButton->show(); - - // preview - if (fileInfo.direction == ToxFile::RECEIVING) - showPreview(fileInfo.filePath); - - disconnect(Core::getInstance(), nullptr, this, nullptr); + updateWidget(file); } void FileTransferWidget::fileTransferRemotePausedUnpaused(ToxFile file, bool paused) @@ -443,18 +314,146 @@ QString FileTransferWidget::getHumanReadableSize(qint64 size) return QString().setNum(size / pow(1024, exp), 'f', exp > 1 ? 2 : 0).append(suffix[exp]); } -void FileTransferWidget::hideWidgets() +void FileTransferWidget::updateWidgetColor(ToxFile const& file) { - ui->leftButton->hide(); - ui->rightButton->hide(); - ui->progressBar->hide(); - ui->progressLabel->hide(); - ui->etaLabel->hide(); + if (lastStatus == file.status) + return; + + switch (file.status) { + case ToxFile::INITIALIZING: + case ToxFile::PAUSED: + case ToxFile::TRANSMITTING: + setBackgroundColor(Style::getColor(Style::LightGrey), false); + break; + case ToxFile::BROKEN: + case ToxFile::CANCELED: + setBackgroundColor(Style::getColor(Style::Red), true); + break; + case ToxFile::FINISHED: + setBackgroundColor(Style::getColor(Style::Green), true); + break; + } } -void FileTransferWidget::setupButtons() +void FileTransferWidget::updateWidgetText(ToxFile const& file) { - switch (fileInfo.status) { + if (lastStatus == file.status) + return; + + switch (file.status) { + case ToxFile::INITIALIZING: + if (file.direction == ToxFile::SENDING) { + ui->progressLabel->setText(tr("Waiting to send...", "file transfer widget")); + } else { + ui->progressLabel->setText(tr("Accept to receive this file", "file transfer widget")); + } + break; + case ToxFile::PAUSED: + ui->etaLabel->setText(""); + ui->progressLabel->setText(tr("Paused", "file transfer widget")); + break; + case ToxFile::TRANSMITTING: + ui->etaLabel->setText(""); + ui->progressLabel->setText(tr("Resuming...", "file transfer widget")); + break; + case ToxFile::BROKEN: + case ToxFile::CANCELED: + break; + case ToxFile::FINISHED: + break; + } +} + +void FileTransferWidget::updatePreview(ToxFile const& file) +{ + if (lastStatus == file.status) + return; + + switch (file.status) { + case ToxFile::INITIALIZING: + case ToxFile::PAUSED: + case ToxFile::TRANSMITTING: + case ToxFile::BROKEN: + case ToxFile::CANCELED: + if (file.direction == ToxFile::SENDING) { + showPreview(file.filePath); + } + break; + case ToxFile::FINISHED: + showPreview(file.filePath); + break; + } + +} + +void FileTransferWidget::updateFileProgress(ToxFile const& file) +{ + switch (file.status) { + case ToxFile::INITIALIZING: + break; + case ToxFile::PAUSED: + fileProgress.resetSpeed(); + break; + case ToxFile::TRANSMITTING: { + if (!fileProgress.needsUpdate()) + break; + + fileProgress.addSample(file); + auto speed = fileProgress.getSpeed(); + auto progress = fileProgress.getProgress(); + auto remainingTime = fileProgress.getTimeLeftSeconds(); + + ui->progressBar->setValue(static_cast(progress * 100.0)); + + // update UI + if (speed > 0) { + // ETA + QTime toGo = QTime(0, 0).addSecs(remainingTime); + QString format = toGo.hour() > 0 ? "hh:mm:ss" : "mm:ss"; + ui->etaLabel->setText(toGo.toString(format)); + } else { + ui->etaLabel->setText(""); + } + + ui->progressLabel->setText(getHumanReadableSize(speed) + "/s"); + break; + } + case ToxFile::BROKEN: + case ToxFile::CANCELED: + case ToxFile::FINISHED: { + ui->progressBar->hide(); + ui->progressLabel->hide(); + ui->etaLabel->hide(); + break; + } + } +} + +void FileTransferWidget::updateSignals(ToxFile const& file) +{ + if (lastStatus == file.status) + return; + + switch (file.status) { + case ToxFile::CANCELED: + case ToxFile::BROKEN: + case ToxFile::FINISHED: + active = false; + disconnect(Core::getInstance(), nullptr, this, nullptr); + break; + case ToxFile::INITIALIZING: + case ToxFile::PAUSED: + case ToxFile::TRANSMITTING: + break; + } +} + +void FileTransferWidget::setupButtons(ToxFile const& file) +{ + if (lastStatus == file.status) + return; + + switch (file.status) { case ToxFile::TRANSMITTING: ui->leftButton->setIcon(QIcon(Style::getImagePath("fileTransferInstance/pause.svg"))); ui->leftButton->setObjectName("pause"); @@ -479,13 +478,12 @@ void FileTransferWidget::setupButtons() setButtonColor(Style::getColor(Style::LightGrey)); break; - case ToxFile::STOPPED: - case ToxFile::BROKEN: + case ToxFile::INITIALIZING: ui->rightButton->setIcon(QIcon(Style::getImagePath("fileTransferInstance/no.svg"))); ui->rightButton->setObjectName("cancel"); ui->rightButton->setToolTip(tr("Cancel transfer")); - if (fileInfo.direction == ToxFile::SENDING) { + if (file.direction == ToxFile::SENDING) { ui->leftButton->setIcon(QIcon(Style::getImagePath("fileTransferInstance/pause.svg"))); ui->leftButton->setObjectName("pause"); ui->leftButton->setToolTip(tr("Pause transfer")); @@ -494,6 +492,23 @@ void FileTransferWidget::setupButtons() ui->leftButton->setObjectName("accept"); ui->leftButton->setToolTip(tr("Accept transfer")); } + break; + case ToxFile::CANCELED: + case ToxFile::BROKEN: + ui->leftButton->hide(); + ui->rightButton->hide(); + break; + case ToxFile::FINISHED: + ui->leftButton->setIcon(QIcon(Style::getImagePath("fileTransferInstance/yes.svg"))); + ui->leftButton->setObjectName("ok"); + ui->leftButton->setToolTip(tr("Open file")); + ui->leftButton->show(); + + ui->rightButton->setIcon(QIcon(Style::getImagePath("fileTransferInstance/dir.svg"))); + ui->rightButton->setObjectName("dir"); + ui->rightButton->setToolTip(tr("Open file directory")); + ui->rightButton->show(); + break; } } @@ -549,7 +564,8 @@ void FileTransferWidget::showPreview(const QString& filename) } const QByteArray imageFileData = imageFile.readAll(); QImage image = QImage::fromData(imageFileData); - const int exifOrientation = getExifOrientation(imageFileData.constData(), imageFileData.size()); + const int exifOrientation = + getExifOrientation(imageFileData.constData(), imageFileData.size()); if (exifOrientation) { applyTransformation(exifOrientation, image); } @@ -562,13 +578,12 @@ void FileTransferWidget::showPreview(const QString& filename) // Show mouseover preview, but make sure it's not larger than 50% of the screen width/height const QRect desktopSize = QApplication::desktop()->screenGeometry(); const int maxPreviewWidth{desktopSize.width() / 2}; - const int maxPreviewHeight{desktopSize.height() /2}; + const int maxPreviewHeight{desktopSize.height() / 2}; const QImage previewImage = [&image, maxPreviewWidth, maxPreviewHeight]() { if (image.width() > maxPreviewWidth || image.height() > maxPreviewHeight) { - return image.scaled(maxPreviewWidth, maxPreviewHeight, - Qt::KeepAspectRatio, Qt::SmoothTransformation); - } - else { + return image.scaled(maxPreviewWidth, maxPreviewHeight, Qt::KeepAspectRatio, + Qt::SmoothTransformation); + } else { return image; } }(); @@ -578,8 +593,7 @@ void FileTransferWidget::showPreview(const QString& filename) buffer.open(QIODevice::WriteOnly); previewImage.save(&buffer, "PNG"); buffer.close(); - ui->previewButton->setToolTip(""); + ui->previewButton->setToolTip(""); } } @@ -641,12 +655,11 @@ int FileTransferWidget::getExifOrientation(const char* data, const int size) void FileTransferWidget::applyTransformation(const int orientation, QImage& image) { QTransform exifTransform; - switch(static_cast(orientation)) - { + switch (static_cast(orientation)) { case ExifOrientation::TopLeft: break; case ExifOrientation::TopRight: - image = image.mirrored(1,0); + image = image.mirrored(1, 0); break; case ExifOrientation::BottomRight: exifTransform.rotate(180); @@ -673,3 +686,33 @@ void FileTransferWidget::applyTransformation(const int orientation, QImage& imag } image = image.transformed(exifTransform); } + +void FileTransferWidget::updateWidget(ToxFile const& file) +{ + if (fileInfo != file) + return; + + fileInfo = file; + + // If we repainted on every packet our gui would be *very* slow + bool bTransmitNeedsUpdate = fileProgress.needsUpdate(); + + updatePreview(file); + updateFileProgress(file); + updateWidgetText(file); + updateWidgetColor(file); + setupButtons(file); + updateSignals(file); + + lastStatus = file.status; + + // trigger repaint + switch (file.status) { + case ToxFile::TRANSMITTING: + if (!bTransmitNeedsUpdate) + break; + // fallthrough + default: + update(); + } +} diff --git a/src/chatlog/content/filetransferwidget.h b/src/chatlog/content/filetransferwidget.h index 10b418014..fff5ea6ba 100644 --- a/src/chatlog/content/filetransferwidget.h +++ b/src/chatlog/content/filetransferwidget.h @@ -24,6 +24,7 @@ #include #include "src/chatlog/chatlinecontent.h" +#include "src/chatlog/toxfileprogress.h" #include "src/core/toxfile.h" @@ -56,8 +57,12 @@ protected slots: protected: QString getHumanReadableSize(qint64 size); - void hideWidgets(); - void setupButtons(); + void updateWidgetColor(ToxFile const& file); + void updateWidgetText(ToxFile const& file); + void updateFileProgress(ToxFile const& file); + void updateSignals(ToxFile const& file); + void updatePreview(ToxFile const& file); + void setupButtons(ToxFile const& file); void handleButton(QPushButton* btn); void showPreview(const QString& filename); void acceptTransfer(const QString& filepath); @@ -79,28 +84,29 @@ private: static void applyTransformation(const int oritentation, QImage& image); static bool tryRemoveFile(const QString &filepath); + void updateWidget(ToxFile const& file); + private: Ui::FileTransferWidget* ui; + ToxFileProgress fileProgress; ToxFile fileInfo; - QTime lastTick; - quint64 lastBytesSent = 0; QVariantAnimation* backgroundColorAnimation = nullptr; QVariantAnimation* buttonColorAnimation = nullptr; QColor backgroundColor; QColor buttonColor; QColor buttonBackgroundColor; - static const uint8_t TRANSFER_ROLLING_AVG_COUNT = 4; - uint8_t meanIndex = 0; - qreal meanData[TRANSFER_ROLLING_AVG_COUNT] = {0.0}; - bool active; - enum class ExifOrientation { + ToxFile::FileStatus lastStatus = ToxFile::INITIALIZING; + + enum class ExifOrientation + { /* do not change values, this is exif spec * * name corresponds to where the 0 row and 0 column is in form row-column - * i.e. entry 5 here means that the 0'th row corresponds to the left side of the scene and the 0'th column corresponds - * to the top of the captured scene. This means that the image needs to be mirrored and rotated to be displayed. + * i.e. entry 5 here means that the 0'th row corresponds to the left side of the scene and + * the 0'th column corresponds to the top of the captured scene. This means that the image + * needs to be mirrored and rotated to be displayed. */ TopLeft = 1, TopRight = 2, diff --git a/src/chatlog/toxfileprogress.cpp b/src/chatlog/toxfileprogress.cpp new file mode 100644 index 000000000..e1d2f1a9b --- /dev/null +++ b/src/chatlog/toxfileprogress.cpp @@ -0,0 +1,92 @@ +/* + Copyright © 2018 by The qTox Project Contributors + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + qTox is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see . +*/ + +#include "toxfileprogress.h" + +#include "src/core/toxfile.h" + +bool ToxFileProgress::needsUpdate() const +{ + QTime now = QTime::currentTime(); + qint64 dt = lastTick.msecsTo(now); // ms + + if (dt < 1000) { + return false; + } + + return true; +} + +void ToxFileProgress::addSample(ToxFile const& file) +{ + QTime now = QTime::currentTime(); + qint64 dt = lastTick.msecsTo(now); // ms + + if (dt < 1000) { + return; + } + + // ETA, speed + qreal deltaSecs = dt / 1000.0; + + // (can't use ::abs or ::max on unsigned types substraction, they'd just overflow) + quint64 deltaBytes = file.bytesSent > lastBytesSent ? file.bytesSent - lastBytesSent + : lastBytesSent - file.bytesSent; + qreal bytesPerSec = static_cast(static_cast(deltaBytes) / deltaSecs); + + // Update member variables + meanIndex = meanIndex % TRANSFER_ROLLING_AVG_COUNT; + meanData[meanIndex++] = bytesPerSec; + + double meanBytesPerSec = 0.0; + for (size_t i = 0; i < TRANSFER_ROLLING_AVG_COUNT; ++i) + meanBytesPerSec += meanData[i]; + meanBytesPerSec /= static_cast(TRANSFER_ROLLING_AVG_COUNT); + + lastTick = now; + + progress = static_cast(file.bytesSent) / static_cast(file.filesize); + speedBytesPerSecond = meanBytesPerSec; + timeLeftSeconds = (file.filesize - file.bytesSent) / getSpeed(); + + lastBytesSent = file.bytesSent; +} + +void ToxFileProgress::resetSpeed() +{ + meanIndex = 0; + for (auto& item : meanData) { + item = 0; + } +} + +double ToxFileProgress::getProgress() const +{ + return progress; +} + +double ToxFileProgress::getSpeed() const +{ + return speedBytesPerSecond; +} + +double ToxFileProgress::getTimeLeftSeconds() const +{ + return timeLeftSeconds; +} diff --git a/src/chatlog/toxfileprogress.h b/src/chatlog/toxfileprogress.h new file mode 100644 index 000000000..c16626901 --- /dev/null +++ b/src/chatlog/toxfileprogress.h @@ -0,0 +1,53 @@ +/* + Copyright © 2018 by The qTox Project Contributors + + This file is part of qTox, a Qt-based graphical interface for Tox. + + qTox is libre software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + qTox is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with qTox. If not, see . +*/ + +#ifndef TOXFILEPROGRESS_H +#define TOXFILEPROGRESS_H + +#include + +struct ToxFile; + +class ToxFileProgress +{ +public: + bool needsUpdate() const; + void addSample(ToxFile const& file); + void resetSpeed(); + + double getProgress() const; + double getSpeed() const; + double getTimeLeftSeconds() const; + +private: + uint64_t lastBytesSent = 0; + + static const uint8_t TRANSFER_ROLLING_AVG_COUNT = 4; + uint8_t meanIndex = 0; + double meanData[TRANSFER_ROLLING_AVG_COUNT] = {0.0}; + + QTime lastTick = QTime::currentTime(); + + double speedBytesPerSecond; + double timeLeftSeconds; + double progress; +}; + + +#endif // TOXFILEPROGRESS_H diff --git a/src/core/corefile.cpp b/src/core/corefile.cpp index 19a4edd40..44d49518f 100644 --- a/src/core/corefile.cpp +++ b/src/core/corefile.cpp @@ -199,7 +199,7 @@ void CoreFile::cancelFileSend(Core* core, uint32_t friendId, uint32_t fileId) return; } - file->status = ToxFile::STOPPED; + file->status = ToxFile::CANCELED; emit core->fileTransferCancelled(*file); tox_file_control(core->tox.get(), file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); removeFile(friendId, fileId); @@ -212,7 +212,7 @@ void CoreFile::cancelFileRecv(Core* core, uint32_t friendId, uint32_t fileId) qWarning("cancelFileRecv: No such file in queue"); return; } - file->status = ToxFile::STOPPED; + file->status = ToxFile::CANCELED; emit core->fileTransferCancelled(*file); tox_file_control(core->tox.get(), file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); removeFile(friendId, fileId); @@ -225,7 +225,7 @@ void CoreFile::rejectFileRecvRequest(Core* core, uint32_t friendId, uint32_t fil qWarning("rejectFileRecvRequest: No such file in queue"); return; } - file->status = ToxFile::STOPPED; + file->status = ToxFile::CANCELED; emit core->fileTransferCancelled(*file); tox_file_control(core->tox.get(), file->friendId, file->fileNum, TOX_FILE_CONTROL_CANCEL, nullptr); removeFile(friendId, fileId); @@ -379,6 +379,7 @@ void CoreFile::onFileControlCallback(Tox*, uint32_t friendId, uint32_t fileId, if (control == TOX_FILE_CONTROL_CANCEL) { if (file->fileKind != TOX_FILE_KIND_AVATAR) qDebug() << "File tranfer" << friendId << ":" << fileId << "cancelled by friend"; + file->status = ToxFile::CANCELED; emit static_cast(core)->fileTransferCancelled(*file); removeFile(friendId, fileId); } else if (control == TOX_FILE_CONTROL_PAUSE) { @@ -409,6 +410,7 @@ void CoreFile::onFileDataCallback(Tox* tox, uint32_t friendId, uint32_t fileId, // If we reached EOF, ack and cleanup the transfer if (!length) { + file->status = ToxFile::FINISHED; if (file->fileKind != TOX_FILE_KIND_AVATAR) { emit static_cast(core)->fileTransferFinished(*file); emit static_cast(core)->fileUploadFinished(file->filePath); @@ -429,6 +431,7 @@ void CoreFile::onFileDataCallback(Tox* tox, uint32_t friendId, uint32_t fileId, nread = file->file->read((char*)data.get(), length); if (nread <= 0) { qWarning("onFileDataCallback: Failed to read from file"); + file->status = ToxFile::CANCELED; emit static_cast(core)->fileTransferCancelled(*file); tox_file_send_chunk(tox, friendId, fileId, pos, nullptr, 0, nullptr); removeFile(friendId, fileId); @@ -458,14 +461,17 @@ void CoreFile::onFileRecvChunkCallback(Tox* tox, uint32_t friendId, uint32_t fil if (file->bytesSent != position) { 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; emit core->fileTransferCancelled(*file); + } tox_file_control(tox, friendId, fileId, TOX_FILE_CONTROL_CANCEL, nullptr); removeFile(friendId, fileId); return; } if (!length) { + file->status = ToxFile::FINISHED; if (file->fileKind == TOX_FILE_KIND_AVATAR) { QPixmap pic; pic.loadFromData(file->avatarData); diff --git a/src/core/toxfile.cpp b/src/core/toxfile.cpp index bd1ac7665..2dbaf3a54 100644 --- a/src/core/toxfile.cpp +++ b/src/core/toxfile.cpp @@ -28,10 +28,9 @@ ToxFile::ToxFile(uint32_t fileNum, uint32_t friendId, QByteArray filename, QStri , file{new QFile(filePath)} , bytesSent{0} , filesize{0} - , status{STOPPED} + , status{INITIALIZING} , direction{Direction} -{ -} +{} bool ToxFile::operator==(const ToxFile& other) const { diff --git a/src/core/toxfile.h b/src/core/toxfile.h index 358366fb9..755c3393b 100644 --- a/src/core/toxfile.h +++ b/src/core/toxfile.h @@ -11,10 +11,12 @@ struct ToxFile { enum FileStatus { - STOPPED, + INITIALIZING, PAUSED, TRANSMITTING, - BROKEN + BROKEN, + CANCELED, + FINISHED, }; enum FileDirection : bool @@ -26,9 +28,7 @@ struct ToxFile ToxFile() = default; ToxFile(uint32_t FileNum, uint32_t FriendId, QByteArray FileName, QString filePath, FileDirection Direction); - ~ToxFile() - { - } + ~ToxFile() {} bool operator==(const ToxFile& other) const; bool operator!=(const ToxFile& other) const;