mirror of
https://gitlab.com/comunic/comunicmessages
synced 2025-06-20 08:55:17 +00:00
Can load remote images and cache them locally.
This commit is contained in:
163
helpers/imageloadhelper.cpp
Normal file
163
helpers/imageloadhelper.cpp
Normal file
@ -0,0 +1,163 @@
|
||||
#include <QStandardPaths>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QCryptographicHash>
|
||||
#include <QMap>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QImage>
|
||||
#include <QImageReader>
|
||||
#include <QPixmap>
|
||||
#include <QLabel>
|
||||
|
||||
#include "imageloadhelper.h"
|
||||
#include "../config.h"
|
||||
#include "../utils/filesutils.h"
|
||||
|
||||
|
||||
//This header should be called only from this file
|
||||
// (QObject subclass seems not to be declarable in CPP files)
|
||||
#include "../data/qlabelholder.h"
|
||||
|
||||
/**
|
||||
* The list of pending labels for an image
|
||||
*/
|
||||
static QMap<QString, QList<QLabelHolder*>> privateList;
|
||||
|
||||
/**
|
||||
* Network Access Manager used to download images
|
||||
*/
|
||||
static QNetworkAccessManager accessManager;
|
||||
|
||||
/**
|
||||
* The first and the last instance of this object
|
||||
*/
|
||||
static ImageLoadHelper *mHelper = nullptr;
|
||||
|
||||
ImageLoadHelper::ImageLoadHelper(QObject *parent) : QObject(parent)
|
||||
{
|
||||
//Nothing yet
|
||||
}
|
||||
|
||||
void ImageLoadHelper::Load(QLabel *label, const QString &url)
|
||||
{
|
||||
//Construct object if required
|
||||
if(mHelper == nullptr)
|
||||
mHelper = new ImageLoadHelper();
|
||||
|
||||
//Check if the image has already been downloaded
|
||||
if(IsDownloaded(url)){
|
||||
ApplyImage(label, url);
|
||||
return;
|
||||
}
|
||||
|
||||
//Check if download is already running
|
||||
if(privateList.contains(url)){
|
||||
QList<QLabelHolder *> swapList = privateList.take(url);
|
||||
swapList.append(new QLabelHolder(label));
|
||||
privateList.insert(url, swapList);
|
||||
return;
|
||||
}
|
||||
|
||||
//If we get there, we have to launch the download of the image
|
||||
QList<QLabelHolder *> list;
|
||||
list.append(new QLabelHolder(label));
|
||||
privateList.insert(url, list);
|
||||
|
||||
Download(url);
|
||||
}
|
||||
|
||||
void ImageLoadHelper::NetworkError()
|
||||
{
|
||||
qWarning("Image Load Helper error : Network error while connecting to server!");
|
||||
}
|
||||
|
||||
void ImageLoadHelper::NetworkRequestFinished()
|
||||
{
|
||||
//If the request is a success, we can save the image, else we can not do anything
|
||||
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
|
||||
reply->deleteLater();
|
||||
|
||||
if(reply->error() != QNetworkReply::NoError){
|
||||
qWarning("Can not process image because we encountered an error while downloading it!");
|
||||
return;
|
||||
}
|
||||
|
||||
//Save the image
|
||||
QString url = reply->url().toString();
|
||||
QImageReader reader(reply);
|
||||
QImage image = reader.read();
|
||||
|
||||
//Check if the image could not be decode
|
||||
if(image.isNull()){
|
||||
qWarning("Downloaded image from %s is not valid!", url.toStdString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
//Save the image
|
||||
QString file_path = GetImageStoragePath(url);
|
||||
if(!image.save(file_path, "PNG")){
|
||||
qWarning("Could not save image from %s to %s !", url.toStdString().c_str(), file_path.toStdString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
//Process the list of awaiting labels
|
||||
QPixmap pixmap = QPixmap::fromImage(image);
|
||||
QList<QLabelHolder *> labels = privateList.take(url);
|
||||
for(QLabelHolder *currLabel : labels)
|
||||
if(currLabel->label() != nullptr)
|
||||
ApplyImage(currLabel->label(), pixmap);
|
||||
}
|
||||
|
||||
void ImageLoadHelper::SSLErrors()
|
||||
{
|
||||
qWarning("Image Load Helper error : SSL error while connecting to server!");
|
||||
}
|
||||
|
||||
void ImageLoadHelper::Download(const QString &url)
|
||||
{
|
||||
qWarning("Download image located at URL: %s", url.toStdString().c_str());
|
||||
|
||||
QNetworkRequest request;
|
||||
request.setUrl(QUrl(url));
|
||||
request.setRawHeader("User-Agent", "ComunicMessages Images Downloader 1.0");
|
||||
|
||||
QNetworkReply *reply = accessManager.get(request);
|
||||
connect(reply, &QNetworkReply::finished, mHelper, &ImageLoadHelper::NetworkRequestFinished);
|
||||
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), mHelper, SLOT(NetworkError()));
|
||||
connect(reply, &QNetworkReply::sslErrors, mHelper, &ImageLoadHelper::SSLErrors);
|
||||
}
|
||||
|
||||
void ImageLoadHelper::ApplyImage(QLabel *label, const QString &url)
|
||||
{
|
||||
ApplyImage(label, QPixmap(GetImageStoragePath(url)));
|
||||
}
|
||||
|
||||
void ImageLoadHelper::ApplyImage(QLabel *label, const QPixmap &pixmap)
|
||||
{
|
||||
label->setPixmap(pixmap);
|
||||
}
|
||||
|
||||
bool ImageLoadHelper::IsDownloaded(const QString &url)
|
||||
{
|
||||
return QFile(GetImageStoragePath(url)).exists();
|
||||
}
|
||||
|
||||
QString ImageLoadHelper::GetImageStoragePath(const QString &url)
|
||||
{
|
||||
//Containing directory
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
|
||||
+ QDir::separator() + REMOTE_IMAGES_CACHE_DIRECTORY;
|
||||
|
||||
//Check the directory exists. If not, create it
|
||||
if(!FilesUtils::CreateDirectoryIfNotExists(path))
|
||||
qFatal("Could not create images cache directory.");
|
||||
|
||||
//Add separator to path
|
||||
path += QDir::separator();
|
||||
|
||||
//File name
|
||||
path += QString(QCryptographicHash::hash(url.toStdString().c_str(), QCryptographicHash::Md5).toHex());
|
||||
|
||||
return path;
|
||||
}
|
91
helpers/imageloadhelper.h
Normal file
91
helpers/imageloadhelper.h
Normal file
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* ImageLoadHelper - This helper is used to
|
||||
* easily load remote images and caches them
|
||||
*
|
||||
* @author Pierre HUBERT
|
||||
*/
|
||||
|
||||
#ifndef IMAGELOADHELPER_H
|
||||
#define IMAGELOADHELPER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QLabel;
|
||||
|
||||
class ImageLoadHelper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
/**
|
||||
* Load an image into a label
|
||||
*
|
||||
* @param label The label where the image will be applied
|
||||
* @param url The URL of the target image
|
||||
*/
|
||||
static void Load(QLabel *label, const QString &url);
|
||||
|
||||
signals:
|
||||
|
||||
private slots:
|
||||
|
||||
/**
|
||||
* Slot called in case of SSL error
|
||||
*/
|
||||
void SSLErrors();
|
||||
|
||||
/**
|
||||
* Slot called in case of network error
|
||||
*/
|
||||
void NetworkError();
|
||||
|
||||
/**
|
||||
* Slot called when a network request finished
|
||||
*/
|
||||
void NetworkRequestFinished();
|
||||
|
||||
private:
|
||||
//This constructor must be private
|
||||
explicit ImageLoadHelper(QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
* Download an image
|
||||
*
|
||||
* @param url The URL of the image to download
|
||||
*/
|
||||
static void Download(const QString &url);
|
||||
|
||||
/**
|
||||
* Apply an image to a label
|
||||
*
|
||||
* @param label Target label which will receive the image
|
||||
* @param url The remote URL of the image
|
||||
*/
|
||||
static void ApplyImage(QLabel *label, const QString &url);
|
||||
|
||||
/**
|
||||
* Apply an image to a label
|
||||
*
|
||||
* @param label Target label which will receive the image
|
||||
* @param pixamp The pixmap to apply to the label
|
||||
*/
|
||||
static void ApplyImage(QLabel *label, const QPixmap &pixmap);
|
||||
|
||||
/**
|
||||
* Check out whether an image has been already downloaded
|
||||
*
|
||||
* @param url The URL of the target image
|
||||
* @return TRUE for a success / FALSE else
|
||||
*/
|
||||
static bool IsDownloaded(const QString &url);
|
||||
|
||||
/**
|
||||
* Get the storage path of a remote image
|
||||
*
|
||||
* @param url The URL of the remote image
|
||||
* @return Full path to the image
|
||||
*/
|
||||
static QString GetImageStoragePath(const QString &url);
|
||||
};
|
||||
|
||||
#endif // IMAGELOADHELPER_H
|
Reference in New Issue
Block a user