diff --git a/projectfiles/QtCreator/TOX-Qt-GUI.pro b/projectfiles/QtCreator/TOX-Qt-GUI.pro
index 717e331..2abda0d 100644
--- a/projectfiles/QtCreator/TOX-Qt-GUI.pro
+++ b/projectfiles/QtCreator/TOX-Qt-GUI.pro
@@ -92,7 +92,8 @@ SOURCES += \
../../src/frienditemdelegate.cpp \
../../src/editablelabelwidget.cpp \
../../src/esclineedit.cpp \
- ../../src/copyableelidelabel.cpp
+ ../../src/copyableelidelabel.cpp \
+ ../../src/filetransferstate.cpp \
HEADERS += \
../../src/mainwindow.hpp \
@@ -135,7 +136,8 @@ HEADERS += \
../../src/frienditemdelegate.hpp \
../../src/editablelabelwidget.hpp \
../../src/esclineedit.hpp \
- ../../src/copyableelidelabel.hpp
+ ../../src/copyableelidelabel.hpp \
+ ../../src/filetransferstate.hpp
### ToxCore section. Please keep it alphabetical ###
diff --git a/resources/icons/attach.png b/resources/icons/attach.png
new file mode 100644
index 0000000..169a845
Binary files /dev/null and b/resources/icons/attach.png differ
diff --git a/resources/resources.qrc b/resources/resources.qrc
index 36af562..bdead89 100644
--- a/resources/resources.qrc
+++ b/resources/resources.qrc
@@ -36,5 +36,6 @@
icons/arrow_redo.png
icons/arrow_undo.png
DejaVuSans.ttf
+ icons/attach.png
diff --git a/src/chatpagewidget.cpp b/src/chatpagewidget.cpp
index 5d06d66..105df97 100644
--- a/src/chatpagewidget.cpp
+++ b/src/chatpagewidget.cpp
@@ -25,6 +25,7 @@
#include
#include
#include
+#include
ChatPageWidget::ChatPageWidget(int friendId, QWidget* parent) :
QWidget(parent), friendId(friendId)
@@ -42,15 +43,25 @@ ChatPageWidget::ChatPageWidget(int friendId, QWidget* parent) :
emoticonButton = new QToolButton(inputPanel);
emoticonButton->setPopupMode(QToolButton::InstantPopup);
emoticonButton->setIcon(QIcon(":/icons/emoticons/emotion_smile.png"));
- emoticonButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
+ emoticonButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
emoticonButton->setMenu(menu);
connect(menu, &EmoticonMenu::insertEmoticon, input, &InputTextWidget::insertHtml);
+ filesendButton = new QToolButton(this);
+ filesendButton->setIcon(QIcon(":/icons/attach.png"));
+ filesendButton->setToolTip(tr("Send file"));
+ filesendButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ connect(filesendButton, &QToolButton::clicked, this, &ChatPageWidget::promptSendFile);
+
+ QVBoxLayout *buttonlayout = new QVBoxLayout();
+ buttonlayout->addWidget(emoticonButton);
+ buttonlayout->addWidget(filesendButton);
+
QHBoxLayout *inputLayout = new QHBoxLayout(inputPanel);
inputLayout->setContentsMargins(0,0,0,0);
inputLayout->setSpacing(2);
inputLayout->addWidget(input);
- inputLayout->addWidget(emoticonButton);
+ inputLayout->addLayout(buttonlayout);
QSplitter* splitter = new QSplitter(this);
splitter->setOrientation(Qt::Vertical);
@@ -109,3 +120,78 @@ void ChatPageWidget::actionSentResult(const QString &message)
{
display->appendAction(username, message, true);
}
+
+quint8 ChatPageWidget::fileSendReceived(quint8 filenumber, quint64 filesize, const QString& filename)
+{
+ QMessageBox::StandardButton ret = QMessageBox::question(this,
+ tr("File Transfer"),
+ tr("%1 is sending you a file `%2', accept?").arg(username).arg(filename));
+
+ quint8 msg_id = TOX_FILECONTROL_KILL;
+
+ if (ret == QMessageBox::Yes) {
+ QString saveFilename = QFileDialog::getSaveFileName(this,
+ tr("Save file"), filename);
+
+ if (!FileTransferState::checkPermission(saveFilename)) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("Failed to open `%1' for writing").arg(saveFilename));
+ } else {
+ FileTransferState* state = new FileTransferState(friendId, filenumber,
+ filesize, saveFilename);
+ states.insert(filenumber, state);
+ display->appendProgress(saveFilename, state, false);
+ msg_id = TOX_FILECONTROL_ACCEPT;
+ }
+ }
+ return msg_id;
+}
+
+void ChatPageWidget::fileControlReceived(unsigned int receive_send, quint8 filenumber, quint8 control_type, const QByteArray& data)
+{
+ if (receive_send == 0 && control_type == TOX_FILECONTROL_FINISHED) {
+ FileTransferState* state = states[filenumber];
+ states.remove(filenumber);
+ delete state;
+ } else if (receive_send == 1 && control_type == TOX_FILECONTROL_ACCEPT) {
+ FileTransferState* state = new FileTransferState(friendId, filenumber,
+ QFileInfo(currentSendFilename).size(), currentSendFilename,
+ FileTransferState::SEND);
+ states.insert(filenumber, state);
+ display->appendProgress(currentSendFilename, state, true);
+ emit sendFile(state);
+ }
+}
+
+void ChatPageWidget::fileDataReceived(quint8 filenumber, const QByteArray& data)
+{
+ FileTransferState* state = states[filenumber];
+ if (state->writeData(data) == -1) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("failed to write data for `%1'").arg(state->fileName()));
+ states.remove(filenumber);
+ delete state;
+ }
+}
+
+void ChatPageWidget::fileSendCompletedReceived(int filenumber)
+{
+ FileTransferState* state = states[filenumber];
+ states.remove(filenumber);
+ delete state;
+}
+
+void ChatPageWidget::promptSendFile(void)
+{
+ QString filename = QFileDialog::getOpenFileName(this, tr("Select a file"));
+ if (filename.length()) {
+ if (!FileTransferState::checkPermission(filename,
+ FileTransferState::SEND)) {
+ QMessageBox::critical(this, tr("Error"),
+ tr("Failed to open `%1' for reading").arg(filename));
+ } else {
+ currentSendFilename = filename;
+ emit sendFileRequest(filename);
+ }
+ }
+}
diff --git a/src/chatpagewidget.hpp b/src/chatpagewidget.hpp
index 51f1328..b3f0576 100644
--- a/src/chatpagewidget.hpp
+++ b/src/chatpagewidget.hpp
@@ -19,7 +19,13 @@
#include "frienditemwidget.hpp"
#include "inputtextwidget.hpp"
+#include "filetransferstate.hpp"
+#include
+
+#include
+#include
+#include
#include
#include
#include
@@ -40,24 +46,33 @@ class ChatPageWidget : public QWidget
private:
FriendItemWidget* friendItem;
MessageDisplayWidget *display;
+ QMap states;
InputTextWidget* input;
+ QToolButton *filesendButton;
QToolButton *emoticonButton;
int friendId;
QString username;
Status status;
+ QString currentSendFilename;
public slots:
void messageReceived(const QString& message);
void messageSentResult(const QString& message, int messageId);
void actionReceived(const QString& message);
void actionSentResult(const QString& message);
+ quint8 fileSendReceived(quint8 filenumber, quint64 filesize, const QString& filename);
+ void fileControlReceived(unsigned int receive_send, quint8 filenumber, quint8 control_type, const QByteArray& data);
+ void fileDataReceived(quint8 filenumber, const QByteArray& data);
+ void fileSendCompletedReceived(int filenumber);
+ void promptSendFile(void);
signals:
void sendMessage(const QString& message);
void sendAction(const QString& action);
-
+ void sendFile(FileTransferState* state);
+ void sendFileRequest(const QString& filename);
};
#endif // CHATPAGEWIDGET_HPP
diff --git a/src/core.cpp b/src/core.cpp
index 6c0d754..67fd93a 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -19,6 +19,9 @@
#include
#include
+#include
+#include
+#include
Core::Core() :
tox(nullptr)
@@ -37,12 +40,12 @@ Core::~Core()
void Core::onFriendRequest(uint8_t* cUserId, uint8_t* cMessage, uint16_t cMessageSize, void* core)
{
- emit static_cast(core)->friendRequestRecieved(CUserId::toString(cUserId), CString::toString(cMessage, cMessageSize));
+ emit static_cast(core)->friendRequestReceived(CUserId::toString(cUserId), CString::toString(cMessage, cMessageSize));
}
void Core::onFriendMessage(Tox*/* tox*/, int friendId, uint8_t* cMessage, uint16_t cMessageSize, void* core)
{
- emit static_cast(core)->friendMessageRecieved(friendId, CString::toString(cMessage, cMessageSize));
+ emit static_cast(core)->friendMessageReceived(friendId, CString::toString(cMessage, cMessageSize));
}
void Core::onFriendNameChange(Tox*/* tox*/, int friendId, uint8_t* cName, uint16_t cNameSize, void* core)
@@ -85,6 +88,20 @@ void Core::onAction(Tox*/* tox*/, int friendId, uint8_t *cMessage, uint16_t cMes
emit static_cast(core)->actionReceived(friendId, CString::toString(cMessage, cMessageSize));
}
+void Core::onFileSendRequest(Tox*, int friendId, uint8_t filenumber, uint64_t filesize, uint8_t *filename, uint16_t filename_length, void *core)
+{
+ emit static_cast(core)->fileSendRequestReceived(friendId, filenumber, filesize, CString::toString(filename, filename_length));
+}
+void Core::onFileControl(Tox*, int friendId, uint8_t receive_send, uint8_t filenumber, uint8_t control_type, uint8_t *data, uint16_t length, void *core)
+{
+ emit static_cast(core)->fileControlReceived(friendId, receive_send, filenumber, control_type, QByteArray((const char*)data, length));
+}
+
+void Core::onFileData(Tox*, int friendId, uint8_t filenumber, uint8_t *data, uint16_t length, void *core)
+{
+ emit static_cast(core)->fileDataReceived(friendId, filenumber, QByteArray((const char*)data, length));
+}
+
void Core::acceptFriendRequest(const QString& userId)
{
int friendId = tox_add_friend_norequest(tox, CUserId(userId).data());
@@ -188,6 +205,7 @@ void Core::bootstrapDht()
void Core::process()
{
tox_do(tox);
+ sendFiles();
#ifdef DEBUG
//we want to see the debug messages immediately
fflush(stdout);
@@ -195,6 +213,44 @@ void Core::process()
checkConnection();
}
+void Core::sendFiles()
+{
+ for (QList::iterator it = fileSenders.begin();
+ it != fileSenders.end();) {
+
+ FileTransferState* state = *it;
+ int len = 0;
+ char* buf = state->buffer();
+ int chunk_size = state->chunkSize();
+ int fn = state->fileNumber();
+ int fid = state->friendId();
+ bool completed = false;
+
+ while (true) {
+ len = state->readData(buf, chunk_size);
+
+ if (len == 0) {
+ tox_file_send_control(tox, fid, 0, fn,
+ TOX_FILECONTROL_FINISHED, NULL, 0);
+ completed = true;
+ break;
+ } else {
+ if (tox_file_send_data(tox, fid, fn, (uint8_t*)buf, len)) {
+ break;
+ }
+ state->readComplete();
+ }
+ }
+
+ if (completed) {
+ emit fileSendCompleted(fid, fn);
+ fileSenders.erase(it++);
+ } else {
+ it++;
+ }
+ }
+}
+
void Core::checkConnection()
{
static bool isConnected = false;
@@ -224,6 +280,9 @@ void Core::start()
tox_callback_status_message(tox, onStatusMessageChanged, this);
tox_callback_user_status(tox, onUserStatusChanged, this);
tox_callback_connection_status(tox, onConnectionStatusChanged, this);
+ tox_callback_file_send_request(tox, onFileSendRequest, this);
+ tox_callback_file_control(tox, onFileControl, this);
+ tox_callback_file_data(tox, onFileData, this);
uint8_t friendAddress[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(tox, friendAddress);
@@ -242,6 +301,23 @@ void Core::start()
timer->start();
}
+void Core::fileSendRequest(int friendId, const QString& filename)
+{
+ tox_new_file_sender(tox, friendId, QFileInfo(filename).size(),
+ (uint8_t*)(const char*)filename.toUtf8(), filename.length() + 1);
+}
+
+void Core::sendFile(int friendId, FileTransferState* state)
+{
+ int chunk_size = tox_file_data_size(tox, friendId);
+ state->createBuf(chunk_size);
+ fileSenders.append(state);
+}
+
+void Core::fileSendReply(int friendId, quint8 filenumber, quint8 message_id)
+{
+ tox_file_send_control(tox, friendId, 1, filenumber, message_id, NULL, 0);
+}
// CData
diff --git a/src/core.hpp b/src/core.hpp
index 70672d9..03fc3c8 100644
--- a/src/core.hpp
+++ b/src/core.hpp
@@ -18,6 +18,7 @@
#define CORE_HPP
#include "status.hpp"
+#include "filetransferstate.hpp"
#include
@@ -40,11 +41,15 @@ class Core : public QObject
static void onUserStatusChanged(Tox* tox, int friendId, TOX_USERSTATUS userstatus, void* core);
static void onConnectionStatusChanged(Tox* tox, int friendId, uint8_t status, void* core);
static void onAction(Tox* tox, int friendId, uint8_t* cMessage, uint16_t cMessageSize, void* core);
+ static void onFileSendRequest(Tox *m, int, uint8_t, uint64_t, uint8_t *, uint16_t, void *);
+ static void onFileControl(Tox *m, int, uint8_t, uint8_t, uint8_t, uint8_t *, uint16_t, void *);
+ static void onFileData(Tox *m, int, uint8_t, uint8_t *, uint16_t length, void *);
void checkConnection();
Tox* tox;
QTimer* timer;
+ QList fileSenders;
class CData
{
@@ -55,7 +60,6 @@ class Core : public QObject
protected:
explicit CData(const QString& data, uint16_t byteSize);
virtual ~CData();
-
static QString toString(uint8_t* cData, uint16_t cDataSize);
private:
@@ -127,15 +131,21 @@ public slots:
void setStatus(Status status);
void process();
+ void sendFiles();
void bootstrapDht();
+ void fileSendRequest(int friendId, const QString& filename);
+ void sendFile(int friendId, FileTransferState* state);
+ void fileSendReply(int friendId, quint8 filenumber, quint8 message_id);
+
+
signals:
void connected();
void disconnected();
- void friendRequestRecieved(const QString& userId, const QString& message);
- void friendMessageRecieved(int friendId, const QString& message);
+ void friendRequestReceived(const QString& userId, const QString& message);
+ void friendMessageReceived(int friendId, const QString& message);
void friendAdded(int friendId, const QString& userId);
@@ -162,6 +172,11 @@ public slots:
void failedToStart();
+ void fileSendRequestReceived(int friendId, quint8 filenumber, quint64 filesize, const QString& filename);
+ void fileControlReceived(int friendId, unsigned int receive_send, quint8 filenumber, quint8 control_type, const QByteArray& data);
+ void fileDataReceived(int friendId, quint8 filenumber, const QByteArray& data);
+
+ void fileSendCompleted(int friendId, int filenumber);
};
#endif // CORE_HPP
diff --git a/src/filetransferstate.cpp b/src/filetransferstate.cpp
new file mode 100644
index 0000000..ad4833c
--- /dev/null
+++ b/src/filetransferstate.cpp
@@ -0,0 +1,108 @@
+/*
+ Copyright (C) 2013 by Wei-Ning Huang
+
+ This file is part of Tox Qt GUI.
+
+ This program is free 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.
+ This program 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 COPYING file for more details.
+*/
+
+#include "filetransferstate.hpp"
+#include
+
+FileTransferState::FileTransferState(int _friendId, int _filenumber, quint64 _filesize, const QString& _filename, int mode)
+ : file(_filename)
+{
+ friendid = _friendId;
+ filenumber = _filenumber;
+ filename = _filename;
+ filesize = _filesize;;
+ transfered = 0;
+ buf = NULL;
+ ack = true;
+
+ QIODevice::OpenMode m = (mode == RECEIVE)? QIODevice::WriteOnly: QIODevice::ReadOnly;
+ file.open(m);
+}
+
+FileTransferState::~FileTransferState()
+{
+ file.close();
+ if (buf) {
+ delete [] buf;
+ }
+}
+
+
+bool FileTransferState::checkPermission(const QString& filename, int mode)
+{
+ QIODevice::OpenMode m = (mode == RECEIVE)? QIODevice::WriteOnly: QIODevice::ReadOnly;
+ return QFile(filename).open(m);
+}
+
+QString FileTransferState::fileName()
+{
+ return filename;
+}
+
+int FileTransferState::friendId()
+{
+ return friendid;
+}
+
+int FileTransferState::fileNumber()
+{
+ return filenumber;
+}
+
+int FileTransferState::writeData(const QByteArray& data)
+{
+ qint64 len = file.write(data.data(), data.length());
+ if (len != data.length()) {
+ return -1;
+ }
+ transfered += len;
+ emit progressChanged((int)(transfered * 100.0 / filesize));
+ return len;
+}
+
+qint64 FileTransferState::readData(char* buf, int max_size)
+{
+ if (ack) {
+ readLength = file.read(buf, max_size);
+ ack = false;
+ }
+ return readLength;
+}
+
+void FileTransferState::readComplete() {
+ ack = true;
+ transfered += readLength;
+ emit progressChanged((int)(transfered * 100.0 / filesize));
+}
+
+void FileTransferState::createBuf(int size)
+{
+ if (buf) {
+ delete [] buf;
+ }
+ chunksize = size;
+ buf = new char[size];
+}
+
+char* FileTransferState::buffer()
+{
+ return buf;
+}
+
+int FileTransferState::chunkSize()
+{
+ return chunksize;
+}
diff --git a/src/filetransferstate.hpp b/src/filetransferstate.hpp
new file mode 100644
index 0000000..18e6102
--- /dev/null
+++ b/src/filetransferstate.hpp
@@ -0,0 +1,70 @@
+/*
+ Copyright (C) 2013 by Wei-Ning Huang
+
+ This file is part of Tox Qt GUI.
+
+ This program is free 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.
+ This program 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 COPYING file for more details.
+*/
+
+#ifndef FILETRANSFERSTATE_HPP
+#define FILETRANSFERSTATE_HPP
+
+#include
+#include
+#include
+#include
+
+class FileTransferState: public QObject
+{
+ Q_OBJECT
+
+public:
+ enum {
+ RECEIVE = 0,
+ SEND
+ };
+
+ static bool checkPermission(const QString& filename, int mode = RECEIVE);
+
+ FileTransferState(int friendId, int filenumber, quint64 filesize,
+ const QString& filename, int mode = RECEIVE);
+ ~FileTransferState();
+
+ QString fileName();
+ int friendId();
+ int fileNumber();
+
+ int writeData(const QByteArray& data);
+ qint64 readData(char* buf, int max_size);
+ void readComplete();
+
+ void createBuf(int size);
+ char* buffer();
+ int chunkSize();
+
+signals:
+ void progressChanged(int percentage);
+
+private:
+ int friendid;
+ int filenumber;
+ QString filename;
+ quint64 filesize;
+ quint64 transfered;
+ int readLength;
+ bool ack;
+ QFile file;
+
+ char* buf;
+ int chunksize;
+};
+
+#endif /* FILETRANSFERSTATE_HPP */
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index c9e77ed..991dc2a 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -116,11 +116,11 @@ MainWindow::MainWindow(QWidget* parent)
connect(core, &Core::connected, this, &MainWindow::onConnected);
connect(core, &Core::disconnected, this, &MainWindow::onDisconnected);
- connect(core, &Core::friendRequestRecieved, this, &MainWindow::onFriendRequestRecieved);
+ connect(core, &Core::friendRequestReceived, this, &MainWindow::onFriendRequestReceived);
connect(core, SIGNAL(friendStatusChanged(int, Status)), friendsWidget, SLOT(setStatus(int, Status)));
connect(core, &Core::friendAddressGenerated, ourUserItem, &OurUserItemWidget::setFriendAddress);
connect(core, &Core::friendAdded, friendsWidget, &FriendsWidget::addFriend);
- connect(core, &Core::friendMessageRecieved, pages, &PagesWidget::messageReceived);
+ connect(core, &Core::friendMessageReceived, pages, &PagesWidget::messageReceived);
connect(core, &Core::actionReceived, pages, &PagesWidget::actionReceived);
connect(core, &Core::friendUsernameChanged, friendsWidget, &FriendsWidget::setUsername);
connect(core, &Core::friendUsernameChanged, pages, &PagesWidget::usernameChanged);
@@ -133,6 +133,15 @@ MainWindow::MainWindow(QWidget* parent)
connect(core, &Core::friendStatusMessageChanged, friendsWidget, &FriendsWidget::setStatusMessage);
connect(core, &Core::friendStatusMessageChanged, pages, &PagesWidget::statusMessageChanged);
+ connect(core, &Core::fileSendRequestReceived, pages, &PagesWidget::fileSendRequestReceived);
+ connect(core, &Core::fileControlReceived, pages, &PagesWidget::fileControl);
+ connect(core, &Core::fileDataReceived, pages, &PagesWidget::fileData);
+ connect(core, &Core::fileSendCompleted, pages, &PagesWidget::fileSendCompleted);
+
+ connect(pages, &PagesWidget::fileSendRequest, core, &Core::fileSendRequest);
+ connect(pages, &PagesWidget::sendFile, core, &Core::sendFile);
+ connect(pages, &PagesWidget::fileSendReply, core, &Core::fileSendReply);
+
connect(core, &Core::failedToStart, this, &MainWindow::onFailedToStartCore);
coreThread->start(/*QThread::IdlePriority*/);
@@ -178,7 +187,7 @@ void MainWindow::closeEvent(QCloseEvent *event)
QMainWindow::closeEvent(event);
}
-void MainWindow::onFriendRequestRecieved(const QString& userId, const QString& message)
+void MainWindow::onFriendRequestReceived(const QString& userId, const QString& message)
{
FriendRequestDialog dialog(this, userId, message);
diff --git a/src/mainwindow.hpp b/src/mainwindow.hpp
index 17c90ec..d1f2272 100644
--- a/src/mainwindow.hpp
+++ b/src/mainwindow.hpp
@@ -50,7 +50,7 @@ private slots:
void onAddFriendButtonClicked();
void onConnected();
void onDisconnected();
- void onFriendRequestRecieved(const QString &userId, const QString &message);
+ void onFriendRequestReceived(const QString &userId, const QString &message);
void onFailedToRemoveFriend(int friendId);
void onFailedToAddFriend(const QString& userId);
void onFailedToStartCore();
diff --git a/src/messagedisplaywidget.cpp b/src/messagedisplaywidget.cpp
index ad144a8..ef3a56c 100644
--- a/src/messagedisplaywidget.cpp
+++ b/src/messagedisplaywidget.cpp
@@ -25,6 +25,8 @@
#include
#include
#include
+#include
+#include
#include "Settings/settings.hpp"
#include "smileypack.hpp"
@@ -68,6 +70,17 @@ void MessageDisplayWidget::appendMessage(const QString &name, const QString &mes
mainlayout->addWidget(row);
}
+void MessageDisplayWidget::appendProgress(const QString &filename, FileTransferState* state, bool isOur)
+{
+ connect(verticalScrollBar(), &QScrollBar::rangeChanged, this, &MessageDisplayWidget::moveScrollBarToBottom, Qt::UniqueConnection);
+ QProgressBar *row = new QProgressBar(this);
+ row->setRange(0, 100);
+ row->setFormat(QString("%1 - %p%").arg(QFileInfo(filename).baseName()));
+ connect(state, &FileTransferState::progressChanged, row, &QProgressBar::setValue);
+ mainlayout->addWidget(row);
+}
+
+
void MessageDisplayWidget::prependMessage(const QString &name, const QString &message/*, const QString ×tamp*/, int messageId, bool isOur)
{
disconnect(verticalScrollBar(), &QScrollBar::rangeChanged, this, &MessageDisplayWidget::moveScrollBarToBottom);
diff --git a/src/messagedisplaywidget.hpp b/src/messagedisplaywidget.hpp
index d3cabe7..1e6a7ec 100644
--- a/src/messagedisplaywidget.hpp
+++ b/src/messagedisplaywidget.hpp
@@ -19,10 +19,13 @@
#include
+#include "filetransferstate.hpp"
+
class QHBoxLayout;
class QVBoxLayout;
class QPropertyAnimation;
+
/*! New message display widget.
*
* CSS classes for styling
@@ -51,6 +54,8 @@ class MessageDisplayWidget : public QScrollArea
void prependMessage(const QString &name, const QString &message, int messageId, bool isOur);
void appendAction(const QString &name, const QString &message, bool isOur);
+ void appendProgress(const QString &filename, FileTransferState* state, bool isOur);
+
int scrollPos() const;
signals:
diff --git a/src/pageswidget.cpp b/src/pageswidget.cpp
index 12eca43..e7e0a2f 100644
--- a/src/pageswidget.cpp
+++ b/src/pageswidget.cpp
@@ -19,6 +19,7 @@
#include
+// PagesWidget
PagesWidget::PagesWidget(QWidget* parent) :
QStackedWidget(parent)
{
@@ -45,6 +46,8 @@ void PagesWidget::addPage(int friendId, const QString& username)
chatPage->setUsername(username);
connect(chatPage, &ChatPageWidget::sendMessage, this, &PagesWidget::onMessageSent);
connect(chatPage, &ChatPageWidget::sendAction, this, &PagesWidget::onActionToSend);
+ connect(chatPage, &ChatPageWidget::sendFile, this, &PagesWidget::onFileToSend);
+ connect(chatPage, &ChatPageWidget::sendFileRequest, this, &PagesWidget::onFileRequestToSend);
addWidget(chatPage);
qDebug() << "page" << friendId << "added" << count();
}
@@ -89,6 +92,18 @@ void PagesWidget::onActionToSend(const QString &action)
emit sendAction(chatPage->getFriendId(), action);
}
+void PagesWidget::onFileToSend(FileTransferState* state)
+{
+ ChatPageWidget* chatPage = static_cast(sender());
+ emit sendFile(chatPage->getFriendId(), state);
+}
+
+void PagesWidget::onFileRequestToSend(const QString& filename)
+{
+ ChatPageWidget* chatPage = static_cast(sender());
+ emit fileSendRequest(chatPage->getFriendId(), filename);
+}
+
void PagesWidget::messageReceived(int friendId, const QString &message)
{
widget(friendId)->messageReceived(message);
@@ -113,3 +128,24 @@ void PagesWidget::actionResult(int friendId, const QString &action, int success)
widget(friendId)->messageSentResult(action, success);
}
}
+
+void PagesWidget::fileSendRequestReceived(int friendId, quint8 filenumber, quint64 filesize, const QString& filename)
+{
+ quint8 msg_id = widget(friendId)->fileSendReceived(filenumber, filesize, filename);
+ emit fileSendReply(friendId, filenumber, msg_id);
+}
+
+void PagesWidget::fileControl(int friendId, unsigned int receive_send, quint8 filenumber, quint8 control_type, const QByteArray& data)
+{
+ widget(friendId)->fileControlReceived(receive_send, filenumber, control_type, data);
+}
+
+void PagesWidget::fileData(int friendId, quint8 filenumber, const QByteArray& data)
+{
+ widget(friendId)->fileDataReceived(filenumber, data);
+}
+
+void PagesWidget::fileSendCompleted(int friendId, int filenumber)
+{
+ widget(friendId)->fileSendCompletedReceived(filenumber);
+}
diff --git a/src/pageswidget.hpp b/src/pageswidget.hpp
index 201f72f..2986a19 100644
--- a/src/pageswidget.hpp
+++ b/src/pageswidget.hpp
@@ -20,6 +20,8 @@
#include "chatpagewidget.hpp"
#include
+#include
+#include
class PagesWidget : public QStackedWidget
{
@@ -30,9 +32,15 @@ class PagesWidget : public QStackedWidget
private:
ChatPageWidget* widget(int friendId) const;
+signals:
+ void sendFile(int friendId, FileTransferState* state);
+ void fileSendReply(int friendId, quint8 filenumber, quint8 message_id);
+
private slots:
void onMessageSent(const QString& message);
void onActionToSend(const QString& action);
+ void onFileToSend(FileTransferState* state);
+ void onFileRequestToSend(const QString& filename);
public slots:
void addPage(int friendId, const QString& username);
@@ -47,7 +55,13 @@ public slots:
void messageSentResult(int friendId, const QString& message, int messageId);
void actionResult(int friendId, const QString &action, int success);
+ void fileSendRequestReceived(int friendId, quint8 filenumber, quint64 filesize, const QString& filename);
+ void fileControl(int friendId, unsigned int receive_send, quint8 filenumber, quint8 control_type, const QByteArray& data);
+ void fileData(int friendId, quint8 filenumber, const QByteArray& data);
+ void fileSendCompleted(int friendId, int filenumber);
+
signals:
+ void fileSendRequest(int friendId, const QString& filename);
void sendMessage(int friendId, const QString& message);
void sendAction(int friendId, const QString& action);