mirror of
https://gitlab.com/comunic/comunicmessages
synced 2024-12-04 11:14:09 +00:00
Can send image to conversations
This commit is contained in:
parent
0148f7aaa5
commit
9100c14dfd
@ -1,4 +1,5 @@
|
||||
#include <QNetworkReply>
|
||||
#include <QFile>
|
||||
|
||||
#include "apirequest.h"
|
||||
|
||||
@ -38,6 +39,31 @@ void APIRequest::addBool(QString name, bool value)
|
||||
mArguments.append(APIRequestParameter(name, value ? "true" : "false"));
|
||||
}
|
||||
|
||||
void APIRequest::addFileFromPath(const QString &name, const QString &path, const QString &fileType)
|
||||
{
|
||||
//Determine files name for the request
|
||||
QString partName = name;
|
||||
partName.replace("\"", "\\\"");
|
||||
QString fileName = ("/"+path).split("/").last();
|
||||
fileName.replace("\"", "\\\"");
|
||||
|
||||
QHttpPart part;
|
||||
part.setHeader(QNetworkRequest::ContentTypeHeader, fileType);
|
||||
part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\""+partName+"\"; filename=\""+fileName+"\""));
|
||||
|
||||
QFile *file = new QFile(path);
|
||||
if(!file->open(QIODevice::ReadOnly)){
|
||||
qWarning("Could not open file to send: %s !", path.toStdString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
part.setBodyDevice(file);
|
||||
mParts.append(part);
|
||||
|
||||
//Automatically delete file object once request is completed
|
||||
file->setParent(this);
|
||||
}
|
||||
|
||||
QList<APIRequestParameter> APIRequest::arguments() const
|
||||
{
|
||||
return mArguments;
|
||||
@ -52,3 +78,13 @@ void APIRequest::setNetworkReply(QNetworkReply *networkReply)
|
||||
{
|
||||
mNetworkReply = networkReply;
|
||||
}
|
||||
|
||||
QList<QHttpPart> *APIRequest::parts()
|
||||
{
|
||||
return &mParts;
|
||||
}
|
||||
|
||||
bool APIRequest::hasParts() const
|
||||
{
|
||||
return mParts.size() > 0;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QJsonDocument>
|
||||
#include <QHttpPart>
|
||||
|
||||
#include "apirequestparameter.h"
|
||||
|
||||
@ -50,6 +51,15 @@ public:
|
||||
*/
|
||||
void addBool(QString name, bool value);
|
||||
|
||||
/**
|
||||
* Add a file from filesystem path
|
||||
*
|
||||
* @param name The name of the file to add
|
||||
* @param path The path to the file
|
||||
* @param fileType The type of the file to add
|
||||
*/
|
||||
void addFileFromPath(const QString &name, const QString &path, const QString &fileType);
|
||||
|
||||
/**
|
||||
* Get the entire list of arguments of the request
|
||||
*
|
||||
@ -57,6 +67,14 @@ public:
|
||||
*/
|
||||
QList<APIRequestParameter> arguments() const;
|
||||
|
||||
/**
|
||||
* Get the list of HTTP parts included with this request
|
||||
*
|
||||
* @return Pointer on the list containing the list of parts
|
||||
*/
|
||||
QList<QHttpPart> *parts();
|
||||
bool hasParts() const;
|
||||
|
||||
//Get and set network reply associated with the request
|
||||
QNetworkReply *networkReply() const;
|
||||
void setNetworkReply(QNetworkReply *networkReply);
|
||||
@ -91,6 +109,7 @@ public slots:
|
||||
private:
|
||||
QString mURI;
|
||||
QList<APIRequestParameter> mArguments;
|
||||
QList<QHttpPart> mParts;
|
||||
QNetworkReply *mNetworkReply = nullptr;
|
||||
};
|
||||
|
||||
|
@ -24,3 +24,18 @@ void NewConversationMessage::setMessage(const QString &message)
|
||||
{
|
||||
mMessage = message;
|
||||
}
|
||||
|
||||
QString NewConversationMessage::imagePath() const
|
||||
{
|
||||
return mImagePath;
|
||||
}
|
||||
|
||||
bool NewConversationMessage::hasImage() const
|
||||
{
|
||||
return !mImagePath.isEmpty();
|
||||
}
|
||||
|
||||
void NewConversationMessage::setImagePath(const QString &imagePath)
|
||||
{
|
||||
mImagePath = imagePath;
|
||||
}
|
||||
|
@ -22,9 +22,14 @@ public:
|
||||
QString message() const;
|
||||
void setMessage(const QString &message);
|
||||
|
||||
QString imagePath() const;
|
||||
bool hasImage() const;
|
||||
void setImagePath(const QString &imagePath);
|
||||
|
||||
private:
|
||||
int mIDConversation;
|
||||
QString mMessage;
|
||||
QString mImagePath;
|
||||
};
|
||||
|
||||
#endif // NEWCONVERSATIONMESSAGE_H
|
||||
|
@ -30,16 +30,49 @@ void APIHelper::execute(APIRequest *request)
|
||||
request->addString("userToken2", tokens.token2());
|
||||
}
|
||||
|
||||
//Prepare request
|
||||
//See this SO question to learn more : https://stackoverflow.com/questions/2599423
|
||||
QUrlQuery queryData;
|
||||
for(APIRequestParameter param : request->arguments())
|
||||
queryData.addQueryItem(param.name(), param.value());
|
||||
QNetworkReply *reply = nullptr;
|
||||
|
||||
//Send request
|
||||
QNetworkRequest networkRequest((QUrl(requestURL)));
|
||||
networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
QNetworkReply *reply = mNetworkManager.post(networkRequest, queryData.toString(QUrl::FullyEncoded).toUtf8());
|
||||
//Prepare request
|
||||
//Check if the request contains files or not
|
||||
if(!request->hasParts()){
|
||||
|
||||
//See this SO question to learn more : https://stackoverflow.com/questions/2599423
|
||||
QUrlQuery queryData;
|
||||
for(APIRequestParameter param : request->arguments())
|
||||
queryData.addQueryItem(param.name(), param.value());
|
||||
|
||||
//Send request
|
||||
QNetworkRequest networkRequest((QUrl(requestURL)));
|
||||
networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
reply = mNetworkManager.post(networkRequest, queryData.toString(QUrl::FullyEncoded).toUtf8());
|
||||
|
||||
}
|
||||
|
||||
//Multiple entries request
|
||||
else {
|
||||
|
||||
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||
|
||||
//Process the list of "normal" arguments
|
||||
for(APIRequestParameter param : request->arguments()){
|
||||
QHttpPart part;
|
||||
part.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\""+param.name()+"\"");
|
||||
part.setBody(param.value().toStdString().c_str());
|
||||
multiPart->append(part);
|
||||
}
|
||||
|
||||
//Append all the other parts
|
||||
for(int i = 0; i < request->parts()->size(); i++)
|
||||
multiPart->append(request->parts()->at(i));
|
||||
|
||||
//Send request
|
||||
QNetworkRequest networkRequest((QUrl(requestURL)));
|
||||
reply = mNetworkManager.post(networkRequest, multiPart);
|
||||
|
||||
//Delete multipart as soon as the request ends
|
||||
multiPart->setParent(reply);
|
||||
|
||||
}
|
||||
|
||||
//Make connections
|
||||
connect(reply, &QNetworkReply::finished, this, &APIHelper::finished);
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "apihelper.h"
|
||||
#include "conversationhelper.h"
|
||||
#include "../data/apirequest.h"
|
||||
#include "../utils/filesutils.h"
|
||||
|
||||
ConversationHelper::ConversationHelper(QObject *parent) : QObject(parent)
|
||||
{
|
||||
@ -17,6 +18,14 @@ void ConversationHelper::sendMessage(const NewConversationMessage &message)
|
||||
request->addInt("conversationID", message.iDConversation());
|
||||
request->addString("message", message.message());
|
||||
|
||||
//Add image (if any)
|
||||
if(message.hasImage()){
|
||||
|
||||
//Add image to request
|
||||
request->addFileFromPath("image", message.imagePath(), FilesUtils::GetFileMimeType(message.imagePath()));
|
||||
|
||||
}
|
||||
|
||||
connect(request, &APIRequest::finished, this, &ConversationHelper::sendMessageFinished);
|
||||
mAPIHelper->execute(request);
|
||||
}
|
||||
|
BIN
res/baseline_insert_photo_black_48dp.png
Executable file
BIN
res/baseline_insert_photo_black_48dp.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 509 B |
@ -3,5 +3,6 @@
|
||||
<file>baseline_people_black_48dp.png</file>
|
||||
<file>baseline_access_time_black_48dp.png</file>
|
||||
<file>baseline_person_black_48dp.png</file>
|
||||
<file>baseline_insert_photo_black_48dp.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <QDir>
|
||||
#include <QMimeDatabase>
|
||||
|
||||
#include "filesutils.h"
|
||||
|
||||
@ -17,3 +18,8 @@ bool FilesUtils::CreateDirectoryIfNotExists(const QString &path)
|
||||
|
||||
return dir.mkpath(".");
|
||||
}
|
||||
|
||||
QString FilesUtils::GetFileMimeType(const QString &filePath)
|
||||
{
|
||||
return (QMimeDatabase()).mimeTypeForFile(filePath).name();
|
||||
}
|
||||
|
@ -23,6 +23,14 @@ public:
|
||||
* FALSE else
|
||||
*/
|
||||
static bool CreateDirectoryIfNotExists(const QString &path);
|
||||
|
||||
/**
|
||||
* Get the mime type of a file
|
||||
*
|
||||
* @param filePath The path of the file to determine
|
||||
* @return File type
|
||||
*/
|
||||
static QString GetFileMimeType(const QString &filePath);
|
||||
};
|
||||
|
||||
#endif // FILESUTILS_H
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <QMessageBox>
|
||||
#include <algorithm>
|
||||
#include <QTimer>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "conversationwidget.h"
|
||||
#include "ui_conversationwidget.h"
|
||||
@ -40,6 +41,31 @@ ConversationWidget::~ConversationWidget()
|
||||
delete mTimer;
|
||||
}
|
||||
|
||||
void ConversationWidget::setMessageFormImage()
|
||||
{
|
||||
//Check if an image has already been selected by the user
|
||||
if(hasUserSelectedImageToSend()){
|
||||
|
||||
//Ask user confirmation
|
||||
if(QMessageBox::question(
|
||||
this,
|
||||
tr("Unselect image"),
|
||||
tr("Are you sure to remove currently selected image from message ?")
|
||||
) != QMessageBox::Yes)
|
||||
return;
|
||||
|
||||
mPathToCurrentImageInForm = "";
|
||||
}
|
||||
|
||||
//Pick an image
|
||||
else
|
||||
mPathToCurrentImageInForm = QFileDialog::getOpenFileName(this,
|
||||
tr("Choose image to include in the message"), "", tr("Image Files (*.png *.jpg *.jpeg, *.gif)"));
|
||||
|
||||
//Check if we have an image selected
|
||||
refreshPickImageButton();
|
||||
}
|
||||
|
||||
void ConversationWidget::sendMessage()
|
||||
{
|
||||
if(isSendMessageFormLocked()){
|
||||
@ -50,7 +76,7 @@ void ConversationWidget::sendMessage()
|
||||
QString content = ui->messageContentInput->text();
|
||||
|
||||
//Check message length
|
||||
if(content.length() < CONVERSATION_MESSAGE_MIN_LENGTH){
|
||||
if(content.length() < CONVERSATION_MESSAGE_MIN_LENGTH && !hasUserSelectedImageToSend()){
|
||||
QMessageBox::warning(this, tr("Invalid message!"), tr("Specified message is too short!"));
|
||||
return;
|
||||
}
|
||||
@ -63,6 +89,10 @@ void ConversationWidget::sendMessage()
|
||||
newMessage.setIDConversation(mConversation.iD());
|
||||
newMessage.setMessage(content);
|
||||
|
||||
//Include user image (if any)
|
||||
if(hasUserSelectedImageToSend())
|
||||
newMessage.setImagePath(mPathToCurrentImageInForm);
|
||||
|
||||
//Request the message to be sent
|
||||
mConversationHelper->sendMessage(newMessage);
|
||||
}
|
||||
@ -135,6 +165,7 @@ void ConversationWidget::setSendMessageFormLocked(bool lock)
|
||||
{
|
||||
ui->sendMessageButton->setEnabled(!lock);
|
||||
ui->messageContentInput->setEnabled(!lock);
|
||||
ui->addImageButton->setEnabled(!lock);
|
||||
}
|
||||
|
||||
bool ConversationWidget::isSendMessageFormLocked()
|
||||
@ -145,4 +176,21 @@ bool ConversationWidget::isSendMessageFormLocked()
|
||||
void ConversationWidget::resetSendMessageForm()
|
||||
{
|
||||
ui->messageContentInput->setText("");
|
||||
mPathToCurrentImageInForm = "";
|
||||
refreshPickImageButton();
|
||||
}
|
||||
|
||||
void ConversationWidget::refreshPickImageButton()
|
||||
{
|
||||
ui->addImageButton->setFlat(hasUserSelectedImageToSend());
|
||||
}
|
||||
|
||||
void ConversationWidget::on_addImageButton_clicked()
|
||||
{
|
||||
setMessageFormImage();
|
||||
}
|
||||
|
||||
bool ConversationWidget::hasUserSelectedImageToSend()
|
||||
{
|
||||
return !mPathToCurrentImageInForm.isEmpty();
|
||||
}
|
||||
|
@ -32,13 +32,17 @@ public:
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
* Ask the user to choose an image to send with the form
|
||||
*/
|
||||
void setMessageFormImage();
|
||||
|
||||
/**
|
||||
* Send the message entered by the user in the form
|
||||
*/
|
||||
void sendMessage();
|
||||
|
||||
|
||||
|
||||
private slots:
|
||||
|
||||
/**
|
||||
@ -67,8 +71,18 @@ private slots:
|
||||
|
||||
void on_messageContentInput_returnPressed();
|
||||
|
||||
void on_addImageButton_clicked();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Check out whether the user has selected an image to include
|
||||
* to the next message he will send through the form
|
||||
*
|
||||
* @return TRUE if the user has selected an image / FALSE else
|
||||
*/
|
||||
bool hasUserSelectedImageToSend();
|
||||
|
||||
/**
|
||||
* Methods to get and set send message form
|
||||
* lock state
|
||||
@ -76,9 +90,11 @@ private:
|
||||
void setSendMessageFormLocked(bool lock);
|
||||
bool isSendMessageFormLocked();
|
||||
void resetSendMessageForm();
|
||||
void refreshPickImageButton();
|
||||
|
||||
//Private fields
|
||||
Ui::ConversationWidget *ui;
|
||||
QString mPathToCurrentImageInForm;
|
||||
QTimer *mTimer;
|
||||
ConversationHelper *mConversationHelper;
|
||||
Conversation mConversation;
|
||||
|
@ -54,6 +54,20 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addImageButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../res/ressources.qrc">
|
||||
<normaloff>:/baseline_insert_photo_black_48dp.png</normaloff>:/baseline_insert_photo_black_48dp.png</iconset>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="sendMessageButton">
|
||||
<property name="text">
|
||||
@ -65,6 +79,8 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<resources>
|
||||
<include location="../res/ressources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
Loading…
Reference in New Issue
Block a user