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

Simple file transfer widget

This commit is contained in:
Tux3 / Mlkj / !Lev.uXFMLA 2014-06-26 00:30:24 +02:00
parent 8aacd21405
commit ec69308efc
7 changed files with 220 additions and 26 deletions

View File

@ -2,6 +2,7 @@
#include "friend.h"
#include "friendwidget.h"
#include "widget.h"
#include "filetransfertwidget.h"
#include <QFont>
#include <QTime>
#include <QScrollBar>
@ -67,6 +68,7 @@ ChatForm::ChatForm(Friend* chatFriend)
chatArea->setWidget(chatAreaWidget);
connect(Widget::getInstance()->getCore(), &Core::fileSendStarted, this, &ChatForm::startFileSend);
connect(sendButton, SIGNAL(clicked()), this, SLOT(onSendTriggered()));
connect(fileButton, SIGNAL(clicked()), this, SLOT(onAttachClicked()));
connect(msgEdit, SIGNAL(enterPressed()), this, SLOT(onSendTriggered()));
@ -166,8 +168,6 @@ void ChatForm::onAttachClicked()
file.close();
QFileInfo fi(path);
// TODO: Show file send widget
emit sendFile(f->friendId, fi.fileName(), fileData);
}
@ -177,3 +177,34 @@ void ChatForm::onSliderRangeChanged()
if (lockSliderToBottom)
scroll->setValue(scroll->maximum());
}
void ChatForm::startFileSend(ToxFile *file)
{
QLabel *author = new QLabel(Widget::getInstance()->getUsername()), *date = new QLabel();
QScrollBar* scroll = chatArea->verticalScrollBar();
lockSliderToBottom = scroll && scroll->value() == scroll->maximum();
author->setAlignment(Qt::AlignTop | Qt::AlignRight);
date->setAlignment(Qt::AlignTop);
QPalette pal;
pal.setColor(QPalette::WindowText, Qt::gray);
author->setPalette(pal);
if (previousName.isEmpty() || previousName != author->text())
{
if (curRow)
{
mainChatLayout->setRowStretch(curRow, 0);
mainChatLayout->addItem(new QSpacerItem(0,AUTHOR_CHANGE_SPACING),curRow,0,1,3);
curRow++;
}
mainChatLayout->addWidget(author, curRow, 0);
}
FileTransfertWidget* fileTrans = new FileTransfertWidget(file);
previousName = author->text();
mainChatLayout->addWidget(fileTrans, curRow, 1);
mainChatLayout->addWidget(date, curRow, 3);
mainChatLayout->setRowStretch(curRow+1, 1);
mainChatLayout->setRowStretch(curRow, 0);
curRow++;
connect(Widget::getInstance()->getCore(), &Core::fileTransferInfo, fileTrans, &FileTransfertWidget::onFileTransferInfo);
}

View File

@ -12,6 +12,7 @@
#include "chattextedit.h"
#include "ui_widget.h"
#include "core.h"
// Spacing in px inserted when the author of the last message changes
#define AUTHOR_CHANGE_SPACING 5
@ -35,6 +36,9 @@ signals:
void sendMessage(int, QString);
void sendFile(int32_t, QString, QByteArray);
public slots:
void startFileSend(ToxFile* file);
private slots:
void onSendTriggered();
void onAttachClicked();

View File

@ -136,10 +136,26 @@ void Core::onFileSendRequestCallback(Tox* tox, int32_t friendnumber, uint8_t fil
qDebug() << "Core: File send request callback";
}
void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber,
uint8_t control_type, uint8_t *data, uint16_t length, void *userdata)
uint8_t control_type, uint8_t *data, uint16_t length, void *core)
{
ToxFile* file{nullptr};
for (ToxFile& f : fileSendQueue)
{
if (f.fileNum == filenumber)
{
file = &f;
break;
}
}
if (!file)
{
qWarning("Core::onFileControlCallback: No such file in queue");
// TODO: Warn the Friend* that we're aborting (emit)
return;
}
if (control_type == TOX_FILECONTROL_ACCEPT && receive_send == 1)
{
emit static_cast<Core*>(core)->fileTransferAccepted(file);
qDebug() << "Core: File control callback, file accepted";
int chunkSize = tox_file_data_size(tox, friendnumber);
if (chunkSize == -1)
@ -148,21 +164,6 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive
// TODO: Warn the Friend* that we're aborting (emit)
return;
}
ToxFile* file{nullptr};
for (ToxFile& f : fileSendQueue)
{
if (f.fileNum == filenumber)
{
file = &f;
break;
}
}
if (!file)
{
qWarning("Core::onFileControlCallback: No such file in queue");
// TODO: Warn the Friend* that we're aborting (emit)
return;
}
chunkSize = std::min(chunkSize, file->fileData.size());
QByteArray toSend = file->fileData.mid(file->bytesSent, chunkSize);
if (tox_file_send_data(tox, friendnumber, filenumber, (uint8_t*)toSend.data(), toSend.size()) == -1)
@ -178,7 +179,7 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive
{
qWarning("Core::onFileControlCallback: Transfer finished");
tox_file_send_control(tox, friendnumber, 0, filenumber, TOX_FILECONTROL_FINISHED, nullptr, 0);
// TODO: Notify the Friend* that we're done sending (emit)
emit static_cast<Core*>(core)->fileTransferFinished(file);
}
else
{
@ -186,6 +187,11 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive
}
}
}
else if (receive_send == 1 && control_type == TOX_FILECONTROL_KILL)
{
file->status = ToxFile::STOPPED;
emit static_cast<Core*>(core)->fileTransferCancelled(file);
}
else
{
qDebug() << QString("Core: File control callback, receive_send=%1, control_type=%2")
@ -262,7 +268,9 @@ void Core::sendFile(int32_t friendId, QString Filename, QByteArray data)
return;
}
fileSendQueue.append(ToxFile(fileNum, friendId, data, fileName));
fileSendQueue.append(ToxFile(fileNum, friendId, data, fileName, ToxFile::SENDING));
emit fileSendStarted(&fileSendQueue.last());
}
void Core::removeFriend(int friendId)
@ -355,6 +363,7 @@ void Core::fileHeartbeat()
{
if (file.status == ToxFile::TRANSMITTING)
{
emit fileTransferInfo(&file);
int chunkSize = tox_file_data_size(tox, file.friendId);
if (chunkSize == -1)
{

19
core.h
View File

@ -50,9 +50,15 @@ struct ToxFile
TRANSMITTING
};
ToxFile(int FileNum, int FriendId, QByteArray FileData, QByteArray FileName)
enum FileDirection : bool
{
SENDING,
RECEIVING
};
ToxFile(int FileNum, int FriendId, QByteArray FileData, QByteArray FileName, FileDirection Direction)
: fileNum(FileNum), friendId(FriendId), fileData{FileData},
fileName{FileName}, bytesSent{0}, status{STOPPED} {}
fileName{FileName}, bytesSent{0}, status{STOPPED}, direction{Direction} {}
int fileNum;
int friendId;
@ -60,6 +66,7 @@ struct ToxFile
QByteArray fileName;
long long bytesSent;
FileStatus status;
FileDirection direction;
};
class Core : public QObject
@ -84,7 +91,7 @@ private:
static void onFileSendRequestCallback(Tox *tox, int32_t friendnumber, uint8_t filenumber, uint64_t filesize,
uint8_t *filename, uint16_t filename_length, void *userdata);
static void onFileControlCallback(Tox *tox, int32_t friendnumber, uint8_t receive_send, uint8_t filenumber,
uint8_t control_type, uint8_t *data, uint16_t length, void *userdata);
uint8_t control_type, uint8_t *data, uint16_t length, void *core);
static void onFileDataCallback(Tox *tox, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata);
void checkConnection();
@ -243,6 +250,12 @@ signals:
void failedToStart();
void fileSendStarted(ToxFile* file);
void fileTransferAccepted(ToxFile* file);
void fileTransferCancelled(ToxFile* file);
void fileTransferFinished(ToxFile* file);
void fileTransferPaused(ToxFile* file);
void fileTransferInfo(ToxFile* file);
};
#endif // CORE_HPP

95
filetransfertwidget.cpp Normal file
View File

@ -0,0 +1,95 @@
#include "filetransfertwidget.h"
FileTransfertWidget::FileTransfertWidget(ToxFile *File)
: file{File}, lastUpdate{QDateTime::currentDateTime()}, lastBytesSent{0}
{
pic=new QLabel(), filename=new QLabel(), size=new QLabel(), speed=new QLabel(), eta=new QLabel();
topright = new QPushButton(), bottomright = new QPushButton();
progress = new QProgressBar();
mainLayout = new QHBoxLayout(), textLayout = new QHBoxLayout();
infoLayout = new QVBoxLayout(), buttonLayout = new QVBoxLayout();
QFont prettysmall;
prettysmall.setPixelSize(10);
QPalette greybg;
greybg.setColor(QPalette::Window, Qt::gray);
setPalette(greybg);
setAutoFillBackground(true);
setFixedSize(250,50);
setLayout(mainLayout);
filename->setText(file->fileName);
filename->setFont(prettysmall);
size->setText(getHumanReadableSize(file->fileData.size()));
size->setFont(prettysmall);
speed->setText("0B/s");
speed->setFont(prettysmall);
eta->setText("00:00");
eta->setFont(prettysmall);
progress->setValue(0);
topright->setIcon(QIcon("img/button icons/no_2x.png"));
if (file->direction == ToxFile::SENDING)
bottomright->setIcon(QIcon("img/button icons/pause_2x.png"));
else
bottomright->setIcon(QIcon("img/button icons/yes_2x.png"));
topright->setIconSize(QSize(25,25));
bottomright->setIconSize(QSize(25,25));
mainLayout->addWidget(pic);
mainLayout->addLayout(infoLayout);
mainLayout->addLayout(buttonLayout);
infoLayout->addWidget(filename);
infoLayout->addLayout(textLayout);
infoLayout->addWidget(progress);
textLayout->addWidget(size);
textLayout->addWidget(speed);
textLayout->addWidget(eta);
textLayout->setMargin(0);
textLayout->setSpacing(5);
}
QString FileTransfertWidget::getHumanReadableSize(int size)
{
static const char* suffix[] = {"B","kB","MB","GB","TB"};
int exp = 0;
if (size)
exp = std::min( (int) (log(size) / log(1000)), (int) (sizeof(suffix) / sizeof(suffix[0]) - 1));
return QString().setNum(size / pow(1000, exp),'g',3).append(suffix[exp]);
}
void FileTransfertWidget::onFileTransferInfo(ToxFile* File)
{
if (File != file)
return;
QDateTime newtime = QDateTime::currentDateTime();
int timediff = lastUpdate.secsTo(newtime);
if (!timediff)
return;
int diff = File->bytesSent - lastBytesSent;
int rawspeed = diff / timediff;
speed->setText(getHumanReadableSize(rawspeed)+"/s");
size->setText(getHumanReadableSize(File->fileData.size()));
if (!rawspeed)
return;
int etaSecs = (File->fileData.size() - File->bytesSent) / rawspeed;
QTime etaTime(0,0);
etaTime = etaTime.addSecs(etaSecs);
eta->setText(etaTime.toString("mm:ss"));
progress->setValue(File->bytesSent*100/File->fileData.size());
lastUpdate = newtime;
lastBytesSent = File->bytesSent;
}
void FileTransfertWidget::onFileTransferCancelled(ToxFile* File)
{
}
void FileTransfertWidget::onFileTransferFinished(ToxFile* File)
{
}

41
filetransfertwidget.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef FILETRANSFERTWIDGET_H
#define FILETRANSFERTWIDGET_H
#include <QWidget>
#include <QLabel>
#include <QPushButton>
#include <QProgressBar>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QDateTime>
#include "core.h"
class ToxFile;
class FileTransfertWidget : public QWidget
{
Q_OBJECT
public:
FileTransfertWidget(ToxFile* File);
public slots:
void onFileTransferInfo(ToxFile* File);
void onFileTransferCancelled(ToxFile* File);
void onFileTransferFinished(ToxFile* File);
private:
QString getHumanReadableSize(int size);
private:
QLabel *pic, *filename, *size, *speed, *eta;
QPushButton *topright, *bottomright;
QProgressBar *progress;
ToxFile* file;
QHBoxLayout *mainLayout, *textLayout;
QVBoxLayout *infoLayout, *buttonLayout;
QDateTime lastUpdate;
long long lastBytesSent;
};
#endif // FILETRANSFERTWIDGET_H

View File

@ -32,7 +32,8 @@ SOURCES += main.cpp\
groupwidget.cpp \
group.cpp \
grouplist.cpp \
groupchatform.cpp
groupchatform.cpp \
filetransfertwidget.cpp
HEADERS += widget.h \
core.h \
@ -43,7 +44,6 @@ HEADERS += widget.h \
editablelabelwidget.h \
elidelabel.h \
copyableelidelabel.h \
elidelabel.h \
esclineedit.h \
friendlist.h \
friend.h \
@ -54,7 +54,8 @@ HEADERS += widget.h \
groupwidget.h \
group.h \
grouplist.h \
groupchatform.h
groupchatform.h \
filetransfertwidget.h
FORMS += widget.ui