mirror of
https://gitee.com/spark-store-project/spark-store
synced 2025-07-03 12:15:59 +08:00
* 更换搜索服务器域名为星火的域名 * 更新搜索服务器为线上服务器 * 完成搜索功能 * 解决搜索结果图标锯齿问题 * 更新appitem的样式 * 完成应用搜索列表的滚动问题 * 合并master分支 * 添加一些文件到忽略列表 * 更新项目结构 * 更新搜索列表UI * 添加 QtNetworkService库
332 lines
12 KiB
C++
332 lines
12 KiB
C++
/**********************************************************
|
|
Author: Qt君
|
|
微信公众号: Qt君(文章首发)
|
|
Website: qtbig.com(后续更新)
|
|
Email: 2088201923@qq.com
|
|
QQ交流群: 732271126
|
|
LISCENSE: MIT
|
|
**********************************************************/
|
|
#include "HttpResponse.h"
|
|
|
|
#include <QRegExp>
|
|
#include <QStringList>
|
|
#include <QByteArray>
|
|
#include <QNetworkConfigurationManager>
|
|
#include <QMetaEnum>
|
|
#include <QEventLoop>
|
|
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
|
|
#define T2S(t) (QString(#t).remove(QRegExp("\\s"))) //type to string
|
|
|
|
#define _exec(target, type, arg) \
|
|
if (target.canConvert<std::function<void (type)> >()) { \
|
|
std::function<void (type)> func = target.value<std::function<void (type)> >(); func(arg); \
|
|
} \
|
|
else
|
|
|
|
#define _exec2(target, type1, type2, arg1, arg2) \
|
|
if (target.canConvert<std::function<void (type1, type2)> >()) { \
|
|
std::function<void (type1, type2)> func = target.value<std::function<void (type1, type2)> >(); func(arg1, arg2); \
|
|
} else
|
|
|
|
using namespace AeaQt;
|
|
|
|
static const QMap<HttpResponse::SupportMethod, QMap<QString, QVariant>> methodParams =
|
|
{
|
|
{
|
|
HttpResponse::onResponse_QNetworkReply_A_Pointer,
|
|
{
|
|
{"types", QStringList({T2S(QNetworkReply*)})},
|
|
{"lambda", T2S(std::function<void (QNetworkReply*)>)},
|
|
{"signal", SIGNAL(finished(QNetworkReply*))},
|
|
{"isAutoInfer", true}
|
|
}
|
|
},
|
|
{
|
|
HttpResponse::onResponse_QByteArray,
|
|
{
|
|
{"types", QStringList({T2S(QByteArray)})},
|
|
{"lambda", T2S(std::function<void (QByteArray)>)},
|
|
{"signal", SIGNAL(finished(QByteArray))},
|
|
{"isAutoInfer", true}
|
|
}
|
|
},
|
|
{
|
|
HttpResponse::onResponse_QVariantMap,
|
|
{
|
|
{"types", QStringList({T2S(QVariantMap)})},
|
|
{"lambda", T2S(std::function<void (QVariantMap)>)},
|
|
{"signal", SIGNAL(finished(QVariantMap))},
|
|
{"isAutoInfer", true}
|
|
}
|
|
},
|
|
{
|
|
HttpResponse::onDownloadProgress_qint64_qint64,
|
|
{
|
|
{"types", QStringList({T2S(qint64), T2S(qint64)})},
|
|
{"lambda", T2S(std::function<void (qint64, qint64)>)},
|
|
{"signal", SIGNAL(downloadProgress(qint64, qint64))},
|
|
{"isAutoInfer", true}
|
|
}
|
|
},
|
|
{
|
|
HttpResponse::onError_QNetworkReply_To_NetworkError,
|
|
{
|
|
{"types", QStringList({T2S(QNetworkReply::NetworkError)})},
|
|
{"lambda", T2S(std::function<void (QNetworkReply::NetworkError)>)},
|
|
{"signal", SIGNAL(error(QNetworkReply::NetworkError))},
|
|
{"isAutoInfer", true}
|
|
}
|
|
},
|
|
{
|
|
HttpResponse::onError_QString,
|
|
{
|
|
{"types", QStringList({T2S(QString)})},
|
|
{"lambda", T2S(std::function<void (QString)>)},
|
|
{"signal", SIGNAL(error(QString))},
|
|
{"isAutoInfer", true}
|
|
}
|
|
},
|
|
{
|
|
HttpResponse::onError_QNetworkReply_To_NetworkError_QNetworkReply_A_Pointer,
|
|
{
|
|
{"types", QStringList({T2S(QNetworkReply::NetworkError), T2S(QNetworkReply*)})},
|
|
{"lambda", T2S(std::function<void (QNetworkReply::NetworkError, QNetworkReply*)>)},
|
|
{"signal", SIGNAL(error(QNetworkReply::NetworkError, QNetworkReply*))},
|
|
{"isAutoInfer", true}
|
|
}
|
|
},
|
|
{
|
|
HttpResponse::onError_QString_QNetworkReply_A_Poniter,
|
|
{
|
|
{"types", QStringList({T2S(QString), T2S(QNetworkReply*)})},
|
|
{"lambda", T2S(std::function<void (QString, QNetworkReply*)>)},
|
|
{"signal", SIGNAL(error(QString, QNetworkReply*))},
|
|
{"isAutoInfer", true}
|
|
}
|
|
},
|
|
};
|
|
|
|
static int extractCode(const char *member)
|
|
{
|
|
/* extract code, ensure QMETHOD_CODE <= code <= QSIGNAL_CODE */
|
|
return (((int)(*member) - '0') & 0x3);
|
|
}
|
|
|
|
HttpResponse::HttpResponse(QNetworkReply *networkReply,
|
|
const QMultiMap<SupportMethod, QPair<QString, QVariant> > &slotsMap,
|
|
const int &timeout,
|
|
bool isBlock)
|
|
: m_networkReply(networkReply),
|
|
m_slotsMap(slotsMap),
|
|
QObject(networkReply)
|
|
{
|
|
slotsMapOperation(m_slotsMap);
|
|
new HttpResponseTimeout(networkReply, timeout);
|
|
|
|
connect(m_networkReply, SIGNAL(finished()), this, SLOT(onFinished()));
|
|
connect(m_networkReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError)));
|
|
connect(m_networkReply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(onDownloadProgress(qint64, qint64)));
|
|
|
|
if (isBlock) {
|
|
QEventLoop loop;
|
|
QObject::connect(m_networkReply, SIGNAL(finished()), &loop, SLOT(quit()));
|
|
loop.exec();
|
|
}
|
|
}
|
|
|
|
HttpResponse::~HttpResponse()
|
|
{
|
|
}
|
|
|
|
QNetworkReply *HttpResponse::networkReply()
|
|
{
|
|
return m_networkReply;
|
|
}
|
|
|
|
void HttpResponse::onFinished()
|
|
{
|
|
QNetworkReply *reply = m_networkReply;
|
|
if (reply->error() != QNetworkReply::NoError)
|
|
return;
|
|
|
|
if (m_slotsMap.contains(onResponse_QNetworkReply_A_Pointer)) {
|
|
_exec(m_slotsMap.value(onResponse_QNetworkReply_A_Pointer).second, QNetworkReply*, reply) {
|
|
emit finished(reply);
|
|
}
|
|
}
|
|
else if (m_slotsMap.contains((onResponse_QByteArray))) {
|
|
QByteArray result = reply->readAll();
|
|
|
|
_exec(m_slotsMap.value((onResponse_QByteArray)).second, QByteArray, result) {
|
|
emit finished(result);
|
|
}
|
|
|
|
reply->deleteLater();
|
|
}
|
|
else if (m_slotsMap.contains((onResponse_QVariantMap))) {
|
|
QByteArray result = reply->readAll();
|
|
QVariantMap resultMap = QJsonDocument::fromJson(result).object().toVariantMap();
|
|
|
|
_exec(m_slotsMap.value((onResponse_QVariantMap)).second, QVariantMap, resultMap){
|
|
emit finished(resultMap);
|
|
}
|
|
|
|
reply->deleteLater();
|
|
}
|
|
}
|
|
|
|
void HttpResponse::onError(QNetworkReply::NetworkError error)
|
|
{
|
|
QNetworkReply *reply = m_networkReply;
|
|
const QMetaObject & metaObject = QNetworkReply::staticMetaObject;
|
|
QMetaEnum metaEnum = metaObject.enumerator(metaObject.indexOfEnumerator("NetworkError"));
|
|
QString errorString = reply->errorString().isEmpty() ? metaEnum.valueToKey(error) : reply->errorString();
|
|
|
|
if (m_slotsMap.contains((onError_QString_QNetworkReply_A_Poniter))) {
|
|
_exec2(m_slotsMap.value((onError_QString_QNetworkReply_A_Poniter)).second, QString, QNetworkReply*, errorString, reply) {
|
|
emit this->error(errorString, reply);
|
|
}
|
|
}
|
|
else if (m_slotsMap.contains((onError_QNetworkReply_To_NetworkError_QNetworkReply_A_Pointer))) {
|
|
_exec2(m_slotsMap.value((onError_QNetworkReply_To_NetworkError_QNetworkReply_A_Pointer)).second,
|
|
QNetworkReply::NetworkError, QNetworkReply*,
|
|
error, reply) {
|
|
emit this->error(error, reply);
|
|
}
|
|
}
|
|
else if (m_slotsMap.contains((onError_QString))) {
|
|
_exec(m_slotsMap.value((onError_QString)).second, QString, errorString) {
|
|
emit this->error(errorString);
|
|
}
|
|
|
|
reply->deleteLater();
|
|
}
|
|
else if (m_slotsMap.contains((onError_QNetworkReply_To_NetworkError))) {
|
|
_exec(m_slotsMap.value((onError_QNetworkReply_To_NetworkError)).second, QNetworkReply::NetworkError, error) {
|
|
emit this->error(error);
|
|
}
|
|
|
|
reply->deleteLater();
|
|
}
|
|
}
|
|
|
|
void HttpResponse::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
|
{
|
|
if (m_slotsMap.contains((onDownloadProgress_qint64_qint64))) {
|
|
_exec2(m_slotsMap.value((onDownloadProgress_qint64_qint64)).second, qint64, qint64, bytesReceived, bytesTotal) {
|
|
emit downloadProgress(bytesReceived, bytesTotal);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void extractSlot(const QString &respReceiverSlot, QString &extractSlot, QStringList &extractSlotTypes)
|
|
{
|
|
QString slot(respReceiverSlot);
|
|
if (extractCode(respReceiverSlot.toStdString().data()) == QSLOT_CODE && !slot.isEmpty()) {
|
|
slot.remove(0, 1);
|
|
|
|
QString unconvertedSlotType = slot;
|
|
int startIndex = slot.indexOf('(');
|
|
int endIndex = slot.indexOf(')');
|
|
Q_ASSERT(startIndex != -1 && endIndex != -1);
|
|
|
|
extractSlot = slot.remove(startIndex, endIndex-startIndex+1);
|
|
|
|
extractSlotTypes = unconvertedSlotType.mid(startIndex+1, endIndex-startIndex-1)
|
|
.remove(QRegExp("\\s"))
|
|
.split(',');
|
|
}
|
|
}
|
|
|
|
/* from slotMap get [SupportMethod] */
|
|
static HttpResponse::SupportMethod getSupportMethod(const QPair<QString, QVariant> &slotMap) {
|
|
|
|
QMapIterator<HttpResponse::SupportMethod, QMap<QString, QVariant>> iter(methodParams);
|
|
|
|
QString receiverSlot = slotMap.first;
|
|
QString slot;
|
|
QStringList slotTypes;
|
|
extractSlot(receiverSlot, slot, slotTypes);
|
|
|
|
while (iter.hasNext()) {
|
|
iter.next();
|
|
HttpResponse::SupportMethod supportMethod = iter.key();
|
|
QMap<QString, QVariant> value = iter.value();
|
|
if (slotTypes == value.value("types").toStringList()) {
|
|
return supportMethod;
|
|
}
|
|
else if (receiverSlot == value.value("lambda").toString()) {
|
|
return supportMethod;
|
|
}
|
|
}
|
|
|
|
return HttpResponse::Invalid;
|
|
}
|
|
|
|
static void autoInfterConvertedSupportMethod(QMultiMap<HttpResponse::SupportMethod, QPair<QString, QVariant> > &unconvertedSlotsMap)
|
|
{
|
|
QMultiMap<HttpResponse::SupportMethod, QPair<QString, QVariant> > convertedSlotsMap;
|
|
QMapIterator<HttpResponse::SupportMethod, QPair<QString, QVariant> > iter(unconvertedSlotsMap);
|
|
|
|
while (iter.hasNext()) {
|
|
iter.next();
|
|
const HttpResponse::SupportMethod supportMethod = iter.key();
|
|
const QPair<QString, QVariant> slotMap = iter.value();
|
|
|
|
if (supportMethod == HttpResponse::AutoInfer) {
|
|
HttpResponse::SupportMethod supportMethod = getSupportMethod(slotMap);
|
|
if (supportMethod == HttpResponse::Invalid) {
|
|
qDebug()<<"Not find support Method!"<<slotMap.first;
|
|
}
|
|
else {
|
|
if (methodParams[supportMethod].value("isAutoInfer").toBool())
|
|
convertedSlotsMap.insert(supportMethod, slotMap);
|
|
else
|
|
qDebug()<<"This type["<<methodParams[supportMethod].value("types").toString()<<"] does not support automatic derivation";
|
|
}
|
|
}
|
|
else {
|
|
if (methodParams[supportMethod].value("isAutoInfer").toBool())
|
|
convertedSlotsMap.insert(supportMethod, slotMap);
|
|
else
|
|
qDebug()<<"This type["<<methodParams[supportMethod].value("types").toString()<<"] does not support automatic derivation";
|
|
}
|
|
}
|
|
|
|
unconvertedSlotsMap = convertedSlotsMap;
|
|
|
|
}
|
|
|
|
void HttpResponse::slotsMapOperation(QMultiMap<SupportMethod, QPair<QString, QVariant> > &slotsMap)
|
|
{
|
|
autoInfterConvertedSupportMethod(slotsMap);
|
|
|
|
QMapIterator<SupportMethod, QPair<QString, QVariant> > iter(slotsMap);
|
|
while (iter.hasNext()) {
|
|
iter.next();
|
|
SupportMethod supportMethod = iter.key();
|
|
const QPair<QString, QVariant> &slotMap = iter.value();
|
|
|
|
const QString &receiverSlot = slotMap.first;
|
|
QVariant target = slotMap.second;
|
|
const QObject *receiver = target.value<QObject*>();
|
|
|
|
if (receiver) {
|
|
if (methodParams.contains(supportMethod)) {
|
|
connect(this,
|
|
methodParams[supportMethod].value("signal").toString().toStdString().data(),
|
|
receiver,
|
|
receiverSlot.toStdString().data(),
|
|
Qt::QueuedConnection);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
HttpResponse::HttpResponse()
|
|
{
|
|
|
|
}
|