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:
parent
8aacd21405
commit
ec69308efc
35
chatform.cpp
35
chatform.cpp
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
45
core.cpp
45
core.cpp
|
@ -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
19
core.h
|
@ -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
95
filetransfertwidget.cpp
Normal 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
41
filetransfertwidget.h
Normal 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
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user