forked from blue/squawk
first working prototype of file upload
This commit is contained in:
parent
a6e48599aa
commit
166a7ac83a
@ -39,6 +39,7 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
|
|||||||
rm(client.findExtension<QXmppRosterManager>()),
|
rm(client.findExtension<QXmppRosterManager>()),
|
||||||
vm(client.findExtension<QXmppVCardManager>()),
|
vm(client.findExtension<QXmppVCardManager>()),
|
||||||
um(new QXmppUploadRequestManager()),
|
um(new QXmppUploadRequestManager()),
|
||||||
|
dm(client.findExtension<QXmppDiscoveryManager>()),
|
||||||
contacts(),
|
contacts(),
|
||||||
conferences(),
|
conferences(),
|
||||||
maxReconnectTimes(0),
|
maxReconnectTimes(0),
|
||||||
@ -93,6 +94,9 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
|
|||||||
QObject::connect(um, &QXmppUploadRequestManager::slotReceived, this, &Account::onUploadSlotReceived);
|
QObject::connect(um, &QXmppUploadRequestManager::slotReceived, this, &Account::onUploadSlotReceived);
|
||||||
QObject::connect(um, &QXmppUploadRequestManager::requestFailed, this, &Account::onUploadSlotRequestFailed);
|
QObject::connect(um, &QXmppUploadRequestManager::requestFailed, this, &Account::onUploadSlotRequestFailed);
|
||||||
|
|
||||||
|
QObject::connect(dm, &QXmppDiscoveryManager::itemsReceived, this, &Account::onDiscoveryItemsReceived);
|
||||||
|
QObject::connect(dm, &QXmppDiscoveryManager::infoReceived, this, &Account::onDiscoveryInfoReceived);
|
||||||
|
|
||||||
QObject::connect(network, &NetworkAccess::uploadFileComplete, this, &Account::onFileUploaded);
|
QObject::connect(network, &NetworkAccess::uploadFileComplete, this, &Account::onFileUploaded);
|
||||||
QObject::connect(network, &NetworkAccess::uploadFileError, this, &Account::onFileUploadError);
|
QObject::connect(network, &NetworkAccess::uploadFileError, this, &Account::onFileUploadError);
|
||||||
|
|
||||||
@ -196,6 +200,7 @@ void Core::Account::onClientConnected()
|
|||||||
reconnectTimes = maxReconnectTimes;
|
reconnectTimes = maxReconnectTimes;
|
||||||
state = Shared::connected;
|
state = Shared::connected;
|
||||||
cm->setCarbonsEnabled(true);
|
cm->setCarbonsEnabled(true);
|
||||||
|
dm->requestItems(getServer());
|
||||||
emit connectionStateChanged(state);
|
emit connectionStateChanged(state);
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "Something weird had happened - xmpp client reported about successful connection but account wasn't in" << state << "state";
|
qDebug() << "Something weird had happened - xmpp client reported about successful connection but account wasn't in" << state << "state";
|
||||||
@ -613,6 +618,7 @@ void Core::Account::sendMessage(const Shared::Message& data)
|
|||||||
QXmppMessage msg(data.getFrom(), data.getTo(), data.getBody(), data.getThread());
|
QXmppMessage msg(data.getFrom(), data.getTo(), data.getBody(), data.getThread());
|
||||||
msg.setId(data.getId());
|
msg.setId(data.getId());
|
||||||
msg.setType(static_cast<QXmppMessage::Type>(data.getType())); //it is safe here, my type is compatible
|
msg.setType(static_cast<QXmppMessage::Type>(data.getType())); //it is safe here, my type is compatible
|
||||||
|
msg.setOutOfBandUrl(data.getOutOfBandUrl());
|
||||||
|
|
||||||
RosterItem* ri = 0;
|
RosterItem* ri = 0;
|
||||||
std::map<QString, Contact*>::const_iterator itr = contacts.find(data.getPenPalJid());
|
std::map<QString, Contact*>::const_iterator itr = contacts.find(data.getPenPalJid());
|
||||||
@ -671,6 +677,9 @@ void Core::Account::sendMessage(const Shared::Message& data, const QString& path
|
|||||||
void Core::Account::sendMessageWithLocalUploadedFile(Shared::Message msg, const QString& url)
|
void Core::Account::sendMessageWithLocalUploadedFile(Shared::Message msg, const QString& url)
|
||||||
{
|
{
|
||||||
msg.setOutOfBandUrl(url);
|
msg.setOutOfBandUrl(url);
|
||||||
|
if (msg.getBody().size() == 0) {
|
||||||
|
msg.setBody(url);
|
||||||
|
}
|
||||||
sendMessage(msg);
|
sendMessage(msg);
|
||||||
//TODO removal/progress update
|
//TODO removal/progress update
|
||||||
}
|
}
|
||||||
@ -1654,3 +1663,15 @@ void Core::Account::onFileUploadError(const QString& messageId, const QString& e
|
|||||||
pendingMessages.erase(itr);
|
pendingMessages.erase(itr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Core::Account::onDiscoveryItemsReceived(const QXmppDiscoveryIq& items)
|
||||||
|
{
|
||||||
|
for (QXmppDiscoveryIq::Item item : items.items()) {
|
||||||
|
dm->requestInfo(item.jid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::Account::onDiscoveryInfoReceived(const QXmppDiscoveryIq& info)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include <QXmppRosterManager.h>
|
#include <QXmppRosterManager.h>
|
||||||
#include <QXmppCarbonManager.h>
|
#include <QXmppCarbonManager.h>
|
||||||
|
#include <QXmppDiscoveryManager.h>
|
||||||
#include <QXmppMamManager.h>
|
#include <QXmppMamManager.h>
|
||||||
#include <QXmppMucManager.h>
|
#include <QXmppMucManager.h>
|
||||||
#include <QXmppClient.h>
|
#include <QXmppClient.h>
|
||||||
@ -133,6 +134,7 @@ private:
|
|||||||
QXmppRosterManager* rm;
|
QXmppRosterManager* rm;
|
||||||
QXmppVCardManager* vm;
|
QXmppVCardManager* vm;
|
||||||
QXmppUploadRequestManager* um;
|
QXmppUploadRequestManager* um;
|
||||||
|
QXmppDiscoveryManager* dm;
|
||||||
std::map<QString, Contact*> contacts;
|
std::map<QString, Contact*> contacts;
|
||||||
std::map<QString, Conference*> conferences;
|
std::map<QString, Conference*> conferences;
|
||||||
unsigned int maxReconnectTimes;
|
unsigned int maxReconnectTimes;
|
||||||
@ -197,6 +199,8 @@ private slots:
|
|||||||
void onUploadSlotRequestFailed(const QXmppHttpUploadRequestIq& request);
|
void onUploadSlotRequestFailed(const QXmppHttpUploadRequestIq& request);
|
||||||
void onFileUploaded(const QString& messageId, const QString& url);
|
void onFileUploaded(const QString& messageId, const QString& url);
|
||||||
void onFileUploadError(const QString& messageId, const QString& errMsg);
|
void onFileUploadError(const QString& messageId, const QString& errMsg);
|
||||||
|
void onDiscoveryItemsReceived (const QXmppDiscoveryIq& items);
|
||||||
|
void onDiscoveryInfoReceived (const QXmppDiscoveryIq& info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addedAccount(const QString &bareJid);
|
void addedAccount(const QString &bareJid);
|
||||||
|
@ -478,12 +478,12 @@ bool Core::NetworkAccess::isUploading(const QString& path, const QString& messag
|
|||||||
|
|
||||||
void Core::NetworkAccess::uploadFile(const QString& messageId, const QString& path, const QUrl& put, const QUrl& get, const QMap<QString, QString> headers)
|
void Core::NetworkAccess::uploadFile(const QString& messageId, const QString& path, const QUrl& put, const QUrl& get, const QMap<QString, QString> headers)
|
||||||
{
|
{
|
||||||
Transfer* upl = new Transfer({{messageId}, 0, 0, true, path, get.toString(), 0});
|
QFile* file = new QFile(path);
|
||||||
|
Transfer* upl = new Transfer({{messageId}, 0, 0, true, path, get.toString(), file});
|
||||||
QNetworkRequest req(put);
|
QNetworkRequest req(put);
|
||||||
for (QMap<QString, QString>::const_iterator itr = headers.begin(), end = headers.end(); itr != end; itr++) {
|
for (QMap<QString, QString>::const_iterator itr = headers.begin(), end = headers.end(); itr != end; itr++) {
|
||||||
req.setRawHeader(itr.key().toUtf8(), itr.value().toUtf8());
|
req.setRawHeader(itr.key().toUtf8(), itr.value().toUtf8());
|
||||||
}
|
}
|
||||||
QFile* file = new QFile(path);
|
|
||||||
if (file->open(QIODevice::ReadOnly)) {
|
if (file->open(QIODevice::ReadOnly)) {
|
||||||
upl->reply = manager->put(req, file);
|
upl->reply = manager->put(req, file);
|
||||||
|
|
||||||
|
2
external/qxmpp
vendored
2
external/qxmpp
vendored
@ -1 +1 @@
|
|||||||
Subproject commit b18a57daa33f0fefa5f4c63aa7f448b48d302e0d
|
Subproject commit f8c546c5b701c53d708a38a951fcc734eaee7940
|
13
main.cpp
13
main.cpp
@ -79,6 +79,11 @@ int main(int argc, char *argv[])
|
|||||||
QThread* coreThread = new QThread();
|
QThread* coreThread = new QThread();
|
||||||
squawk->moveToThread(coreThread);
|
squawk->moveToThread(coreThread);
|
||||||
|
|
||||||
|
QObject::connect(coreThread, &QThread::started, squawk, &Core::Squawk::start);
|
||||||
|
QObject::connect(&app, &QApplication::aboutToQuit, squawk, &Core::Squawk::stop);
|
||||||
|
QObject::connect(squawk, &Core::Squawk::quit, coreThread, &QThread::quit);
|
||||||
|
QObject::connect(coreThread, &QThread::finished, squawk, &Core::Squawk::deleteLater);
|
||||||
|
|
||||||
QObject::connect(&w, &Squawk::newAccountRequest, squawk, &Core::Squawk::newAccountRequest);
|
QObject::connect(&w, &Squawk::newAccountRequest, squawk, &Core::Squawk::newAccountRequest);
|
||||||
QObject::connect(&w, &Squawk::modifyAccountRequest, squawk, &Core::Squawk::modifyAccountRequest);
|
QObject::connect(&w, &Squawk::modifyAccountRequest, squawk, &Core::Squawk::modifyAccountRequest);
|
||||||
QObject::connect(&w, &Squawk::removeAccountRequest, squawk, &Core::Squawk::removeAccountRequest);
|
QObject::connect(&w, &Squawk::removeAccountRequest, squawk, &Core::Squawk::removeAccountRequest);
|
||||||
@ -129,10 +134,10 @@ int main(int argc, char *argv[])
|
|||||||
QObject::connect(squawk, &Core::Squawk::changeRoomParticipant, &w, &Squawk::changeRoomParticipant);
|
QObject::connect(squawk, &Core::Squawk::changeRoomParticipant, &w, &Squawk::changeRoomParticipant);
|
||||||
QObject::connect(squawk, &Core::Squawk::removeRoomParticipant, &w, &Squawk::removeRoomParticipant);
|
QObject::connect(squawk, &Core::Squawk::removeRoomParticipant, &w, &Squawk::removeRoomParticipant);
|
||||||
QObject::connect(squawk, &Core::Squawk::fileLocalPathResponse, &w, &Squawk::fileLocalPathResponse);
|
QObject::connect(squawk, &Core::Squawk::fileLocalPathResponse, &w, &Squawk::fileLocalPathResponse);
|
||||||
QObject::connect(squawk, &Core::Squawk::downloadFileProgress, &w, &Squawk::downloadFileProgress);
|
QObject::connect(squawk, &Core::Squawk::downloadFileProgress, &w, &Squawk::fileProgress);
|
||||||
QObject::connect(squawk, &Core::Squawk::downloadFileError, &w, &Squawk::downloadFileError);
|
QObject::connect(squawk, &Core::Squawk::downloadFileError, &w, &Squawk::fileError);
|
||||||
QObject::connect(squawk, &Core::Squawk::uploadFileProgress, &w, &Squawk::uploadFileProgress);
|
QObject::connect(squawk, &Core::Squawk::uploadFileProgress, &w, &Squawk::fileProgress);
|
||||||
QObject::connect(squawk, &Core::Squawk::uploadFileError, &w, &Squawk::uploadFileError);
|
QObject::connect(squawk, &Core::Squawk::uploadFileError, &w, &Squawk::fileError);
|
||||||
QObject::connect(squawk, &Core::Squawk::responseVCard, &w, &Squawk::responseVCard);
|
QObject::connect(squawk, &Core::Squawk::responseVCard, &w, &Squawk::responseVCard);
|
||||||
|
|
||||||
coreThread->start();
|
coreThread->start();
|
||||||
|
@ -369,11 +369,11 @@ void Squawk::onConversationDownloadFile(const QString& messageId, const QString&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Squawk::downloadFileProgress(const QString& messageId, qreal value)
|
void Squawk::fileProgress(const QString& messageId, qreal value)
|
||||||
{
|
{
|
||||||
std::map<QString, std::set<Models::Roster::ElId>>::const_iterator itr = requestedFiles.find(messageId);
|
std::map<QString, std::set<Models::Roster::ElId>>::const_iterator itr = requestedFiles.find(messageId);
|
||||||
if (itr == requestedFiles.end()) {
|
if (itr == requestedFiles.end()) {
|
||||||
qDebug() << "downloadFileProgress in UI Squawk but there is nobody waiting for that id" << messageId << ", skipping";
|
qDebug() << "fileProgress in UI Squawk but there is nobody waiting for that id" << messageId << ", skipping";
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
const std::set<Models::Roster::ElId>& convs = itr->second;
|
const std::set<Models::Roster::ElId>& convs = itr->second;
|
||||||
@ -381,17 +381,17 @@ void Squawk::downloadFileProgress(const QString& messageId, qreal value)
|
|||||||
const Models::Roster::ElId& id = *cItr;
|
const Models::Roster::ElId& id = *cItr;
|
||||||
Conversations::const_iterator c = conversations.find(id);
|
Conversations::const_iterator c = conversations.find(id);
|
||||||
if (c != conversations.end()) {
|
if (c != conversations.end()) {
|
||||||
c->second->responseDownloadProgress(messageId, value);
|
c->second->responseFileProgress(messageId, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Squawk::downloadFileError(const QString& messageId, const QString& error)
|
void Squawk::fileError(const QString& messageId, const QString& error)
|
||||||
{
|
{
|
||||||
std::map<QString, std::set<Models::Roster::ElId>>::const_iterator itr = requestedFiles.find(messageId);
|
std::map<QString, std::set<Models::Roster::ElId>>::const_iterator itr = requestedFiles.find(messageId);
|
||||||
if (itr == requestedFiles.end()) {
|
if (itr == requestedFiles.end()) {
|
||||||
qDebug() << "downloadFileError in UI Squawk but there is nobody waiting for that id" << messageId << ", skipping";
|
qDebug() << "fileError in UI Squawk but there is nobody waiting for that id" << messageId << ", skipping";
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
const std::set<Models::Roster::ElId>& convs = itr->second;
|
const std::set<Models::Roster::ElId>& convs = itr->second;
|
||||||
@ -399,7 +399,7 @@ void Squawk::downloadFileError(const QString& messageId, const QString& error)
|
|||||||
const Models::Roster::ElId& id = *cItr;
|
const Models::Roster::ElId& id = *cItr;
|
||||||
Conversations::const_iterator c = conversations.find(id);
|
Conversations::const_iterator c = conversations.find(id);
|
||||||
if (c != conversations.end()) {
|
if (c != conversations.end()) {
|
||||||
c->second->downloadError(messageId, error);
|
c->second->fileError(messageId, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
requestedFiles.erase(itr);
|
requestedFiles.erase(itr);
|
||||||
@ -497,6 +497,9 @@ void Squawk::onConversationMessage(const Shared::Message& msg)
|
|||||||
void Squawk::onConversationMessage(const Shared::Message& msg, const QString& path)
|
void Squawk::onConversationMessage(const Shared::Message& msg, const QString& path)
|
||||||
{
|
{
|
||||||
Conversation* conv = static_cast<Conversation*>(sender());
|
Conversation* conv = static_cast<Conversation*>(sender());
|
||||||
|
std::map<QString, std::set<Models::Roster::ElId>>::iterator itr = requestedFiles.insert(std::make_pair(msg.getId(), std::set<Models::Roster::ElId>())).first;
|
||||||
|
itr->second.insert(Models::Roster::ElId(conv->getAccount(), conv->getJid()));
|
||||||
|
|
||||||
emit sendMessage(conv->getAccount(), msg, path);
|
emit sendMessage(conv->getAccount(), msg, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,10 +98,8 @@ public slots:
|
|||||||
void changeRoomParticipant(const QString& account, const QString& jid, const QString& name, const QMap<QString, QVariant>& data);
|
void changeRoomParticipant(const QString& account, const QString& jid, const QString& name, const QMap<QString, QVariant>& data);
|
||||||
void removeRoomParticipant(const QString& account, const QString& jid, const QString& name);
|
void removeRoomParticipant(const QString& account, const QString& jid, const QString& name);
|
||||||
void fileLocalPathResponse(const QString& messageId, const QString& path);
|
void fileLocalPathResponse(const QString& messageId, const QString& path);
|
||||||
void downloadFileError(const QString& messageId, const QString& error);
|
void fileError(const QString& messageId, const QString& error);
|
||||||
void downloadFileProgress(const QString& messageId, qreal value);
|
void fileProgress(const QString& messageId, qreal value);
|
||||||
void uploadFileError(const QString& messageId, const QString& error);
|
|
||||||
void uploadFileProgress(const QString& messageId, qreal value);
|
|
||||||
void responseVCard(const QString& jid, const Shared::VCard& card);
|
void responseVCard(const QString& jid, const Shared::VCard& card);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -34,11 +34,11 @@ Message::Message(const Shared::Message& source, bool outgoing, const QString& p_
|
|||||||
sender(new QLabel(p_sender)),
|
sender(new QLabel(p_sender)),
|
||||||
text(new QLabel()),
|
text(new QLabel()),
|
||||||
shadow(new QGraphicsDropShadowEffect()),
|
shadow(new QGraphicsDropShadowEffect()),
|
||||||
downloadButton(0),
|
button(0),
|
||||||
file(0),
|
file(0),
|
||||||
progress(0),
|
progress(0),
|
||||||
fileComment(new QLabel()),
|
fileComment(new QLabel()),
|
||||||
hasDownloadButton(false),
|
hasButton(false),
|
||||||
hasProgress(false),
|
hasProgress(false),
|
||||||
hasFile(false),
|
hasFile(false),
|
||||||
commentAdded(false)
|
commentAdded(false)
|
||||||
@ -77,13 +77,13 @@ Message::Message(const Shared::Message& source, bool outgoing, const QString& p_
|
|||||||
body->setGraphicsEffect(shadow);
|
body->setGraphicsEffect(shadow);
|
||||||
|
|
||||||
if (outgoing) {
|
if (outgoing) {
|
||||||
addWidget(body);
|
|
||||||
addStretch();
|
|
||||||
} else {
|
|
||||||
sender->setAlignment(Qt::AlignRight);
|
sender->setAlignment(Qt::AlignRight);
|
||||||
date->setAlignment(Qt::AlignRight);
|
date->setAlignment(Qt::AlignRight);
|
||||||
addStretch();
|
addStretch();
|
||||||
addWidget(body);
|
addWidget(body);
|
||||||
|
} else {
|
||||||
|
addWidget(body);
|
||||||
|
addStretch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,35 +109,28 @@ void Message::setSender(const QString& p_sender)
|
|||||||
sender->setText(p_sender);
|
sender->setText(p_sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Message::addButton(const QIcon& icon, const QString& buttonText, const QString& comment)
|
void Message::addButton(const QIcon& icon, const QString& buttonText)
|
||||||
{
|
{
|
||||||
hideFile();
|
hideFile();
|
||||||
hideProgress();
|
hideProgress();
|
||||||
if (!hasDownloadButton) {
|
if (!hasButton) {
|
||||||
hideComment();
|
hideComment();
|
||||||
if (msg.getBody() == msg.getOutOfBandUrl()) {
|
if (msg.getBody() == msg.getOutOfBandUrl()) {
|
||||||
text->setText("");
|
text->setText("");
|
||||||
text->hide();
|
text->hide();
|
||||||
}
|
}
|
||||||
downloadButton = new QPushButton(icon, buttonText);
|
button = new QPushButton(icon, buttonText);
|
||||||
downloadButton->setToolTip("<a href=\"" + msg.getOutOfBandUrl() + "\">" + msg.getOutOfBandUrl() + "</a>");
|
button->setToolTip("<a href=\"" + msg.getOutOfBandUrl() + "\">" + msg.getOutOfBandUrl() + "</a>");
|
||||||
if (comment.size() != 0) {
|
connect(button, &QPushButton::clicked, this, &Message::buttonClicked);
|
||||||
fileComment->setWordWrap(true);
|
bodyLayout->insertWidget(2, button);
|
||||||
fileComment->setText(comment);
|
hasButton = true;
|
||||||
fileComment->show();
|
|
||||||
}
|
|
||||||
connect(downloadButton, &QPushButton::clicked, this, &Message::downloadFile);
|
|
||||||
bodyLayout->insertWidget(2, fileComment);
|
|
||||||
bodyLayout->insertWidget(3, downloadButton);
|
|
||||||
hasDownloadButton = true;
|
|
||||||
commentAdded = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Message::setProgress(qreal value, const QString& label)
|
void Message::setProgress(qreal value)
|
||||||
{
|
{
|
||||||
hideFile();
|
hideFile();
|
||||||
hideDownload();
|
hideButton();
|
||||||
if (!hasProgress) {
|
if (!hasProgress) {
|
||||||
hideComment();
|
hideComment();
|
||||||
if (msg.getBody() == msg.getOutOfBandUrl()) {
|
if (msg.getBody() == msg.getOutOfBandUrl()) {
|
||||||
@ -146,21 +139,15 @@ void Message::setProgress(qreal value, const QString& label)
|
|||||||
}
|
}
|
||||||
progress = new QProgressBar();
|
progress = new QProgressBar();
|
||||||
progress->setRange(0, 100);
|
progress->setRange(0, 100);
|
||||||
if (label.size() != 0) {
|
|
||||||
fileComment->setText(label);
|
|
||||||
}
|
|
||||||
fileComment->show();
|
|
||||||
bodyLayout->insertWidget(2, progress);
|
bodyLayout->insertWidget(2, progress);
|
||||||
bodyLayout->insertWidget(3, fileComment);
|
|
||||||
hasProgress = true;
|
hasProgress = true;
|
||||||
commentAdded = true;
|
|
||||||
}
|
}
|
||||||
progress->setValue(value * 100);
|
progress->setValue(value * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Message::showFile(const QString& path)
|
void Message::showFile(const QString& path)
|
||||||
{
|
{
|
||||||
hideDownload();
|
hideButton();
|
||||||
hideProgress();
|
hideProgress();
|
||||||
if (!hasFile) {
|
if (!hasFile) {
|
||||||
hideComment();
|
hideComment();
|
||||||
@ -173,16 +160,13 @@ void Message::showFile(const QString& path)
|
|||||||
QStringList parts = type.name().split("/");
|
QStringList parts = type.name().split("/");
|
||||||
QString big = parts.front();
|
QString big = parts.front();
|
||||||
QFileInfo info(path);
|
QFileInfo info(path);
|
||||||
fileComment = new QLabel();
|
|
||||||
if (big == "image") {
|
if (big == "image") {
|
||||||
file = new Image(path);
|
file = new Image(path);
|
||||||
} else {
|
} else {
|
||||||
file = new QLabel();
|
file = new QLabel();
|
||||||
file->setPixmap(QIcon::fromTheme(type.iconName()).pixmap(50));
|
file->setPixmap(QIcon::fromTheme(type.iconName()).pixmap(50));
|
||||||
file->setAlignment(Qt::AlignCenter);
|
file->setAlignment(Qt::AlignCenter);
|
||||||
fileComment->setText(info.fileName());
|
showComment(info.fileName(), true);
|
||||||
fileComment->setWordWrap(true);
|
|
||||||
fileComment->show();
|
|
||||||
}
|
}
|
||||||
file->setContextMenuPolicy(Qt::ActionsContextMenu);
|
file->setContextMenuPolicy(Qt::ActionsContextMenu);
|
||||||
QAction* openAction = new QAction(QIcon::fromTheme("document-new-from-template"), tr("Open"), file);
|
QAction* openAction = new QAction(QIcon::fromTheme("document-new-from-template"), tr("Open"), file);
|
||||||
@ -191,9 +175,7 @@ void Message::showFile(const QString& path)
|
|||||||
});
|
});
|
||||||
file->addAction(openAction);
|
file->addAction(openAction);
|
||||||
bodyLayout->insertWidget(2, file);
|
bodyLayout->insertWidget(2, file);
|
||||||
bodyLayout->insertWidget(3, fileComment);
|
|
||||||
hasFile = true;
|
hasFile = true;
|
||||||
commentAdded = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,12 +188,12 @@ void Message::hideComment()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Message::hideDownload()
|
void Message::hideButton()
|
||||||
{
|
{
|
||||||
if (hasDownloadButton) {
|
if (hasButton) {
|
||||||
downloadButton->deleteLater();
|
button->deleteLater();
|
||||||
downloadButton = 0;
|
button = 0;
|
||||||
hasDownloadButton = false;
|
hasButton = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,3 +214,29 @@ void Message::hideProgress()
|
|||||||
hasProgress = false;;
|
hasProgress = false;;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void Message::showComment(const QString& comment, bool wordWrap)
|
||||||
|
{
|
||||||
|
if (!commentAdded) {
|
||||||
|
int index = 2;
|
||||||
|
if (hasFile) {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
if (hasButton) {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
if (hasProgress) {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
bodyLayout->insertWidget(index, fileComment);
|
||||||
|
fileComment->show();
|
||||||
|
commentAdded = true;
|
||||||
|
}
|
||||||
|
fileComment->setWordWrap(wordWrap);
|
||||||
|
fileComment->setText(comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Shared::Message & Message::getMessage() const
|
||||||
|
{
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -47,13 +47,16 @@ public:
|
|||||||
void setSender(const QString& sender);
|
void setSender(const QString& sender);
|
||||||
QString getId() const;
|
QString getId() const;
|
||||||
QString getFileUrl() const;
|
QString getFileUrl() const;
|
||||||
|
const Shared::Message& getMessage() const;
|
||||||
|
|
||||||
void addButton(const QIcon& icon, const QString& buttonText, const QString& comment = "");
|
void addButton(const QIcon& icon, const QString& buttonText);
|
||||||
|
void showComment(const QString& comment, bool wordWrap = false);
|
||||||
|
void hideComment();
|
||||||
void showFile(const QString& path);
|
void showFile(const QString& path);
|
||||||
void setProgress(qreal value, const QString& label = "");
|
void setProgress(qreal value);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void downloadFile();
|
void buttonClicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Shared::Message msg;
|
Shared::Message msg;
|
||||||
@ -63,20 +66,19 @@ private:
|
|||||||
QLabel* sender;
|
QLabel* sender;
|
||||||
QLabel* text;
|
QLabel* text;
|
||||||
QGraphicsDropShadowEffect* shadow;
|
QGraphicsDropShadowEffect* shadow;
|
||||||
QPushButton* downloadButton;
|
QPushButton* button;
|
||||||
QLabel* file;
|
QLabel* file;
|
||||||
QProgressBar* progress;
|
QProgressBar* progress;
|
||||||
QLabel* fileComment;
|
QLabel* fileComment;
|
||||||
bool hasDownloadButton;
|
bool hasButton;
|
||||||
bool hasProgress;
|
bool hasProgress;
|
||||||
bool hasFile;
|
bool hasFile;
|
||||||
bool commentAdded;
|
bool commentAdded;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void hideDownload();
|
void hideButton();
|
||||||
void hideProgress();
|
void hideProgress();
|
||||||
void hideFile();
|
void hideFile();
|
||||||
void hideComment();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MESSAGE_H
|
#endif // MESSAGE_H
|
||||||
|
@ -30,7 +30,6 @@ MessageLine::MessageLine(bool p_room, QWidget* parent):
|
|||||||
layout(new QVBoxLayout(this)),
|
layout(new QVBoxLayout(this)),
|
||||||
myName(),
|
myName(),
|
||||||
palNames(),
|
palNames(),
|
||||||
views(),
|
|
||||||
uploading(),
|
uploading(),
|
||||||
downloading(),
|
downloading(),
|
||||||
room(p_room),
|
room(p_room),
|
||||||
@ -63,15 +62,15 @@ MessageLine::Position MessageLine::message(const Shared::Message& msg)
|
|||||||
if (room) {
|
if (room) {
|
||||||
if (msg.getFromResource() == myName) {
|
if (msg.getFromResource() == myName) {
|
||||||
sender = myName;
|
sender = myName;
|
||||||
outgoing = false;
|
outgoing = true;
|
||||||
} else {
|
} else {
|
||||||
sender = msg.getFromResource();
|
sender = msg.getFromResource();
|
||||||
outgoing = true;
|
outgoing = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (msg.getOutgoing()) {
|
if (msg.getOutgoing()) {
|
||||||
sender = myName;
|
sender = myName;
|
||||||
outgoing = false;
|
outgoing = true;
|
||||||
} else {
|
} else {
|
||||||
QString jid = msg.getFromJid();
|
QString jid = msg.getFromJid();
|
||||||
std::map<QString, QString>::iterator itr = palNames.find(jid);
|
std::map<QString, QString>::iterator itr = palNames.find(jid);
|
||||||
@ -80,7 +79,7 @@ MessageLine::Position MessageLine::message(const Shared::Message& msg)
|
|||||||
} else {
|
} else {
|
||||||
sender = jid;
|
sender = jid;
|
||||||
}
|
}
|
||||||
outgoing = true;
|
outgoing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +92,8 @@ MessageLine::Position MessageLine::message(const Shared::Message& msg)
|
|||||||
return invalid;
|
return invalid;
|
||||||
}
|
}
|
||||||
if (outgoing) {
|
if (outgoing) {
|
||||||
|
myMessages.insert(std::make_pair(id, message));
|
||||||
|
} else {
|
||||||
if (room) {
|
if (room) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -103,8 +104,6 @@ MessageLine::Position MessageLine::message(const Shared::Message& msg)
|
|||||||
}
|
}
|
||||||
pItr->second.insert(std::make_pair(id, message));
|
pItr->second.insert(std::make_pair(id, message));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
myMessages.insert(std::make_pair(id, message));
|
|
||||||
}
|
}
|
||||||
messageIndex.insert(std::make_pair(id, message));
|
messageIndex.insert(std::make_pair(id, message));
|
||||||
int index = std::distance<Order::const_iterator>(messageOrder.begin(), result.first); //need to make with binary indexed tree
|
int index = std::distance<Order::const_iterator>(messageOrder.begin(), result.first); //need to make with binary indexed tree
|
||||||
@ -130,7 +129,7 @@ MessageLine::Position MessageLine::message(const Shared::Message& msg)
|
|||||||
|
|
||||||
if (msg.hasOutOfBandUrl()) {
|
if (msg.hasOutOfBandUrl()) {
|
||||||
emit requestLocalFile(msg.getId(), msg.getOutOfBandUrl());
|
emit requestLocalFile(msg.getId(), msg.getOutOfBandUrl());
|
||||||
connect(message, &Message::downloadFile, this, &MessageLine::onDownload);
|
connect(message, &Message::buttonClicked, this, &MessageLine::onDownload);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@ -143,6 +142,8 @@ void MessageLine::onDownload()
|
|||||||
Index::const_iterator itr = downloading.find(messageId);
|
Index::const_iterator itr = downloading.find(messageId);
|
||||||
if (itr == downloading.end()) {
|
if (itr == downloading.end()) {
|
||||||
downloading.insert(std::make_pair(messageId, msg));
|
downloading.insert(std::make_pair(messageId, msg));
|
||||||
|
msg->setProgress(0);
|
||||||
|
msg->showComment(tr("Downloading..."));
|
||||||
emit downloadFile(messageId, msg->getFileUrl());
|
emit downloadFile(messageId, msg->getFileUrl());
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "An attempt to initiate download for already downloading file" << msg->getFileUrl() << ", skipping";
|
qDebug() << "An attempt to initiate download for already downloading file" << msg->getFileUrl() << ", skipping";
|
||||||
@ -210,16 +211,11 @@ void MessageLine::hideBusyIndicator()
|
|||||||
|
|
||||||
void MessageLine::fileProgress(const QString& messageId, qreal progress)
|
void MessageLine::fileProgress(const QString& messageId, qreal progress)
|
||||||
{
|
{
|
||||||
Index::const_iterator itr = downloading.find(messageId);
|
Index::const_iterator itr = messageIndex.find(messageId);
|
||||||
if (itr == downloading.end()) {
|
if (itr == messageIndex.end()) {
|
||||||
Index::const_iterator itr = uploading.find(messageId);
|
|
||||||
if (itr == uploading.end()) {
|
|
||||||
//TODO may be some logging, that's not normal
|
//TODO may be some logging, that's not normal
|
||||||
} else {
|
} else {
|
||||||
itr->second->setProgress(progress, tr("Uploading..."));
|
itr->second->setProgress(progress);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
itr->second->setProgress(progress, tr("Downloading..."));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,11 +225,85 @@ void MessageLine::responseLocalFile(const QString& messageId, const QString& pat
|
|||||||
if (itr == messageIndex.end()) {
|
if (itr == messageIndex.end()) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
Index::const_iterator uItr = uploading.find(messageId);
|
||||||
if (path.size() > 0) {
|
if (path.size() > 0) {
|
||||||
|
Index::const_iterator dItr = downloading.find(messageId);
|
||||||
|
if (dItr != downloading.end()) {
|
||||||
|
downloading.erase(dItr);
|
||||||
itr->second->showFile(path);
|
itr->second->showFile(path);
|
||||||
} else {
|
} else {
|
||||||
itr->second->addButton(QIcon::fromTheme("download"), tr("Download"), tr("Push the button to daownload the file"));
|
if (uItr != uploading.end()) {
|
||||||
|
uploading.erase(uItr);
|
||||||
|
std::map<QString, QString>::const_iterator muItr = uploadPaths.find(messageId);
|
||||||
|
if (muItr != uploadPaths.end()) {
|
||||||
|
uploadPaths.erase(muItr);
|
||||||
}
|
}
|
||||||
|
if (room) {
|
||||||
|
removeMessage(messageId);
|
||||||
|
} else {
|
||||||
|
Shared::Message msg = itr->second->getMessage();
|
||||||
|
removeMessage(messageId);
|
||||||
|
msg.setCurrentTime();
|
||||||
|
message(msg);
|
||||||
|
itr = messageIndex.find(messageId);
|
||||||
|
itr->second->showFile(path);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
itr->second->showFile(path); //then it is already cached file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (uItr != uploading.end()) {
|
||||||
|
itr->second->addButton(QIcon::fromTheme("download"), tr("Download"));
|
||||||
|
itr->second->showComment(tr("Push the button to daownload the file"));
|
||||||
|
} else {
|
||||||
|
qDebug() << "An unhandled state for file uploading - empty path";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageLine::removeMessage(const QString& messageId)
|
||||||
|
{
|
||||||
|
Index::const_iterator itr = messageIndex.find(messageId);
|
||||||
|
if (itr != messageIndex.end()) {
|
||||||
|
Message* ui = itr->second;
|
||||||
|
const Shared::Message& msg = ui->getMessage();
|
||||||
|
messageIndex.erase(itr);
|
||||||
|
Order::const_iterator oItr = messageOrder.find(msg.getTime());
|
||||||
|
if (oItr != messageOrder.end()) {
|
||||||
|
messageOrder.erase(oItr);
|
||||||
|
} else {
|
||||||
|
qDebug() << "An attempt to remove message from messageLine, but it wasn't found in order";
|
||||||
|
}
|
||||||
|
if (msg.getOutgoing()) {
|
||||||
|
Index::const_iterator mItr = myMessages.find(messageId);
|
||||||
|
if (mItr != myMessages.end()) {
|
||||||
|
myMessages.erase(mItr);
|
||||||
|
} else {
|
||||||
|
qDebug() << "Error removing message: it seems to be outgoing yet it wasn't found in outgoing messages";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (room) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
QString jid = msg.getFromJid();
|
||||||
|
std::map<QString, Index>::iterator pItr = palMessages.find(jid);
|
||||||
|
if (pItr != palMessages.end()) {
|
||||||
|
Index& pMsgs = pItr->second;
|
||||||
|
Index::const_iterator pmitr = pMsgs.find(messageId);
|
||||||
|
if (pmitr != pMsgs.end()) {
|
||||||
|
pMsgs.erase(pmitr);
|
||||||
|
} else {
|
||||||
|
qDebug() << "Error removing message: it seems to be incoming yet it wasn't found among messages from that penpal";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui->deleteLater();
|
||||||
|
qDebug() << "message" << messageId << "has been removed";
|
||||||
|
} else {
|
||||||
|
qDebug() << "An attempt to remove non existing message from messageLine";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,18 +315,29 @@ void MessageLine::fileError(const QString& messageId, const QString& error)
|
|||||||
if (itr == uploading.end()) {
|
if (itr == uploading.end()) {
|
||||||
//TODO may be some logging, that's not normal
|
//TODO may be some logging, that's not normal
|
||||||
} else {
|
} else {
|
||||||
//itr->second->showError(error);
|
itr->second->showComment(tr("Error uploading file: %1\nYou can try again").arg(QCoreApplication::translate("NetworkErrors", error.toLatin1())), true);
|
||||||
//itr->second->addDownloadDialog();
|
itr->second->addButton(QIcon::fromTheme("upload"), tr("Upload"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
itr->second->addButton(QIcon::fromTheme("download"), tr("Download"),
|
itr->second->addButton(QIcon::fromTheme("download"), tr("Download"));
|
||||||
tr("Error downloading file: %1\nYou can try again").arg(QCoreApplication::translate("NetworkErrors", error.toLatin1())));
|
itr->second->showComment(tr("Error downloading file: %1\nYou can try again").arg(QCoreApplication::translate("NetworkErrors", error.toLatin1())), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageLine::appendMessageWithUpload(const Shared::Message& msg, const QString& path)
|
void MessageLine::appendMessageWithUpload(const Shared::Message& msg, const QString& path)
|
||||||
{
|
{
|
||||||
message(msg);
|
message(msg);
|
||||||
|
QString id = msg.getId();
|
||||||
|
Message* ui = messageIndex.find(id)->second;
|
||||||
|
connect(ui, &Message::buttonClicked, this, &MessageLine::onUpload); //this is in case of retry;
|
||||||
|
ui->setProgress(0);
|
||||||
|
ui->showComment("Uploading...");
|
||||||
|
uploading.insert(std::make_pair(id, ui));
|
||||||
|
uploadPaths.insert(std::make_pair(id, path));
|
||||||
|
emit uploadFile(msg, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MessageLine::onUpload()
|
||||||
|
{
|
||||||
|
//TODO retry
|
||||||
|
}
|
||||||
|
@ -53,6 +53,7 @@ public:
|
|||||||
void fileError(const QString& messageId, const QString& error);
|
void fileError(const QString& messageId, const QString& error);
|
||||||
void fileProgress(const QString& messageId, qreal progress);
|
void fileProgress(const QString& messageId, qreal progress);
|
||||||
void appendMessageWithUpload(const Shared::Message& message, const QString& path);
|
void appendMessageWithUpload(const Shared::Message& message, const QString& path);
|
||||||
|
void removeMessage(const QString& messageId);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void resize(int amount);
|
void resize(int amount);
|
||||||
@ -65,6 +66,7 @@ protected:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onDownload();
|
void onDownload();
|
||||||
|
void onUpload();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Comparator {
|
struct Comparator {
|
||||||
@ -86,7 +88,6 @@ private:
|
|||||||
|
|
||||||
QString myName;
|
QString myName;
|
||||||
std::map<QString, QString> palNames;
|
std::map<QString, QString> palNames;
|
||||||
std::deque<QHBoxLayout*> views;
|
|
||||||
Index uploading;
|
Index uploading;
|
||||||
Index downloading;
|
Index downloading;
|
||||||
bool room;
|
bool room;
|
||||||
|
@ -66,6 +66,7 @@ Conversation::Conversation(bool muc, const QString& mJid, const QString mRes, co
|
|||||||
connect(m_ui->sendButton, &QPushButton::clicked, this, &Conversation::onEnterPressed);
|
connect(m_ui->sendButton, &QPushButton::clicked, this, &Conversation::onEnterPressed);
|
||||||
connect(line, &MessageLine::resize, this, &Conversation::onMessagesResize);
|
connect(line, &MessageLine::resize, this, &Conversation::onMessagesResize);
|
||||||
connect(line, &MessageLine::downloadFile, this, &Conversation::downloadFile);
|
connect(line, &MessageLine::downloadFile, this, &Conversation::downloadFile);
|
||||||
|
connect(line, &MessageLine::uploadFile, this, qOverload<const Shared::Message&, const QString&>(&Conversation::sendMessage));
|
||||||
connect(line, &MessageLine::requestLocalFile, this, &Conversation::requestLocalFile);
|
connect(line, &MessageLine::requestLocalFile, this, &Conversation::requestLocalFile);
|
||||||
connect(m_ui->attachButton, &QPushButton::clicked, this, &Conversation::onAttach);
|
connect(m_ui->attachButton, &QPushButton::clicked, this, &Conversation::onAttach);
|
||||||
|
|
||||||
@ -180,11 +181,34 @@ void Conversation::onEnterPressed()
|
|||||||
{
|
{
|
||||||
QString body(m_ui->messageEditor->toPlainText());
|
QString body(m_ui->messageEditor->toPlainText());
|
||||||
|
|
||||||
|
if (filesToAttach.size() > 0) {
|
||||||
|
for (Badge* badge : filesToAttach) {
|
||||||
|
Shared::Message msg;
|
||||||
|
if (isMuc) {
|
||||||
|
msg.setType(Shared::Message::groupChat);
|
||||||
|
} else {
|
||||||
|
msg.setType(Shared::Message::chat);
|
||||||
|
msg.setToResource(activePalResource);
|
||||||
|
}
|
||||||
|
msg.setFromJid(myJid);
|
||||||
|
msg.setFromResource(myResource);
|
||||||
|
msg.setToJid(palJid);
|
||||||
|
msg.setOutgoing(true);
|
||||||
|
msg.generateRandomId();
|
||||||
|
msg.setCurrentTime();
|
||||||
|
if (body.size() > 0) {
|
||||||
|
msg.setBody(body);
|
||||||
|
}
|
||||||
|
line->appendMessageWithUpload(msg, badge->id);
|
||||||
|
}
|
||||||
|
clearAttachedFiles();
|
||||||
|
} else {
|
||||||
if (body.size() > 0) {
|
if (body.size() > 0) {
|
||||||
m_ui->messageEditor->clear();
|
m_ui->messageEditor->clear();
|
||||||
handleSendMessage(body);
|
handleSendMessage(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Conversation::onMessagesResize(int amount)
|
void Conversation::onMessagesResize(int amount)
|
||||||
{
|
{
|
||||||
@ -294,14 +318,14 @@ void Conversation::onScrollResize()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Conversation::responseDownloadProgress(const QString& messageId, qreal progress)
|
void Conversation::responseFileProgress(const QString& messageId, qreal progress)
|
||||||
{
|
{
|
||||||
line->responseDownloadProgress(messageId, progress);
|
line->fileProgress(messageId, progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Conversation::downloadError(const QString& messageId, const QString& error)
|
void Conversation::fileError(const QString& messageId, const QString& error)
|
||||||
{
|
{
|
||||||
line->downloadError(messageId, error);
|
line->fileError(messageId, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Conversation::responseLocalFile(const QString& messageId, const QString& path)
|
void Conversation::responseLocalFile(const QString& messageId, const QString& path)
|
||||||
|
@ -75,8 +75,8 @@ public:
|
|||||||
void responseArchive(const std::list<Shared::Message> list);
|
void responseArchive(const std::list<Shared::Message> list);
|
||||||
void showEvent(QShowEvent * event) override;
|
void showEvent(QShowEvent * event) override;
|
||||||
void responseLocalFile(const QString& messageId, const QString& path);
|
void responseLocalFile(const QString& messageId, const QString& path);
|
||||||
void downloadError(const QString& messageId, const QString& error);
|
void fileError(const QString& messageId, const QString& error);
|
||||||
void responseDownloadProgress(const QString& messageId, qreal progress);
|
void responseFileProgress(const QString& messageId, qreal progress);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sendMessage(const Shared::Message& message);
|
void sendMessage(const Shared::Message& message);
|
||||||
|
Loading…
Reference in New Issue
Block a user