1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

refactor(files): Refactor FileTransferWidget

Rational here is that the current FileTransferWidget is quite
entangled with core logic. If we are going to instantiate the
FileTransferWidget without an active file transfer the widget needs to
behave sanely without getting messages from toxcore. This changeset is
an attempt to allow us to move from any FileTransferWidget state to any
other state without having to go through the appropriate state
transitions.
This commit is contained in:
Mick Sayson 2018-09-24 20:08:30 -07:00
parent f188409b8c
commit 157be30b11
8 changed files with 385 additions and 184 deletions

View File

@ -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

View File

@ -41,6 +41,7 @@
#include <math.h>
// 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<qreal>(file.bytesSent) / static_cast<qreal>(file.filesize);
ui->progressBar->setValue(static_cast<int>(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<int>(static_cast<qreal>(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<qreal>(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<int>(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("<img src=data:image/png;base64," + imageData.toBase64()
+ "/>");
ui->previewButton->setToolTip("<img src=data:image/png;base64," + imageData.toBase64() + "/>");
}
}
@ -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<ExifOrientation>(orientation))
{
switch (static_cast<ExifOrientation>(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();
}
}

View File

@ -24,6 +24,7 @@
#include <QWidget>
#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,

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<int>(static_cast<qreal>(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<qreal>(TRANSFER_ROLLING_AVG_COUNT);
lastTick = now;
progress = static_cast<double>(file.bytesSent) / static_cast<double>(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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef TOXFILEPROGRESS_H
#define TOXFILEPROGRESS_H
#include <QTime>
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

View File

@ -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*>(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*>(core)->fileTransferFinished(*file);
emit static_cast<Core*>(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*>(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);

View File

@ -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
{

View File

@ -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;