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