This commit is contained in:
朱子楚\zhuzi 2023-09-04 20:45:56 +08:00
commit f60eaec07c
16 changed files with 666 additions and 387 deletions

View File

@ -263,3 +263,28 @@ zxing-cpp
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
************************************************************************************
ChartJs2QML
MIT License
Copyright (c) 2020 ChartJs2QML contributors (starting with Elypson, Michael A. Voelkel, https://github.com/Elypson)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -10,14 +10,57 @@ import "qrc:///example/qml/component"
FluContentPage{ FluContentPage{
title:"Http" title:"Http"
property string cacheDirPath: FluTools.getApplicationDirPath() + "/cache/http"
FluHttp{ FluHttp{
id:http id:http
} }
FluHttp{
id:http_cache_ifnonecacherequest
cacheMode:FluHttpType.IfNoneCacheRequest
cacheDir:cacheDirPath
}
FluHttp{
id:http_cache_requestfailedreadcache
cacheMode:FluHttpType.RequestFailedReadCache
cacheDir:cacheDirPath
}
FluHttp{
id:http_cache_firstcachethenrequest
cacheMode:FluHttpType.FirstCacheThenRequest
cacheDir:cacheDirPath
}
HttpCallable{
id:callable
onStart: {
showLoading()
}
onFinish: {
hideLoading()
}
onError:
(status,errorString,result)=>{
console.debug(status+";"+errorString+";"+result)
}
onSuccess:
(result)=>{
text_info.text = result
console.debug(result)
}
onCache:
(result)=>{
text_info.text = result
console.debug(result)
}
}
Flickable{ Flickable{
id:layout_flick id:layout_flick
width: 160 width: 200
clip: true clip: true
anchors{ anchors{
top: parent.top top: parent.top
@ -36,20 +79,6 @@ FluContentPage{
implicitHeight: 36 implicitHeight: 36
text: "Get请求" text: "Get请求"
onClicked: { onClicked: {
var callable = {}
callable.onStart = function(){
showLoading()
}
callable.onFinish = function(){
hideLoading()
}
callable.onSuccess = function(result){
text_info.text = result
console.debug(result)
}
callable.onError = function(status,errorString){
console.debug(status+";"+errorString)
}
http.get("https://httpbingo.org/get",callable) http.get("https://httpbingo.org/get",callable)
} }
} }
@ -58,20 +87,6 @@ FluContentPage{
implicitHeight: 36 implicitHeight: 36
text: "Post表单请求" text: "Post表单请求"
onClicked: { onClicked: {
var callable = {}
callable.onStart = function(){
showLoading()
}
callable.onFinish = function(){
hideLoading()
}
callable.onSuccess = function(result){
text_info.text = result
console.debug(result)
}
callable.onError = function(status,errorString){
console.debug(status+";"+errorString)
}
var param = {} var param = {}
param.custname = "朱子楚" param.custname = "朱子楚"
param.custtel = "1234567890" param.custtel = "1234567890"
@ -84,20 +99,6 @@ FluContentPage{
implicitHeight: 36 implicitHeight: 36
text: "Post Json请求" text: "Post Json请求"
onClicked: { onClicked: {
var callable = {}
callable.onStart = function(){
showLoading()
}
callable.onFinish = function(){
hideLoading()
}
callable.onSuccess = function(result){
text_info.text = result
console.debug(result)
}
callable.onError = function(status,errorString){
console.debug(status+";"+errorString)
}
var param = {} var param = {}
param.custname = "朱子楚" param.custname = "朱子楚"
param.custtel = "1234567890" param.custtel = "1234567890"
@ -110,20 +111,6 @@ FluContentPage{
implicitHeight: 36 implicitHeight: 36
text: "Post String请求" text: "Post String请求"
onClicked: { onClicked: {
var callable = {}
callable.onStart = function(){
showLoading()
}
callable.onFinish = function(){
hideLoading()
}
callable.onSuccess = function(result){
text_info.text = result
console.debug(result)
}
callable.onError = function(status,errorString){
console.debug(status+";"+errorString)
}
var param = "我命由我不由天" var param = "我命由我不由天"
http.postString("https://httpbingo.org/post",callable,param) http.postString("https://httpbingo.org/post",callable,param)
} }
@ -146,9 +133,86 @@ FluContentPage{
file_dialog.open() file_dialog.open()
} }
} }
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "FirstCacheThenRequest缓存"
onClicked: {
var param = {}
param.cacheMode = "FirstCacheThenRequest"
http_cache_firstcachethenrequest.post("https://httpbingo.org/post",callable,param)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "RequestFailedReadCache缓存"
onClicked: {
var param = {}
param.cacheMode = "RequestFailedReadCache"
http_cache_requestfailedreadcache.post("https://httpbingo.org/post",callable,param)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "IfNoneCacheRequest缓存"
onClicked: {
var param = {}
param.cacheMode = "IfNoneCacheRequest"
http_cache_ifnonecacherequest.post("https://httpbingo.org/post",callable,param)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "删除缓存"
onClicked: {
console.debug(FluTools.removeDir(cacheDirPath))
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "清空右边数据"
onClicked: {
text_info.text = ""
}
}
} }
} }
HttpCallable{
id:callable_upload
onStart: {
btn_upload.disabled = true
}
onFinish: {
btn_upload.disabled = false
btn_upload.text = "上传文件"
layout_upload_file_size.visible = false
text_upload_file_size.text = ""
}
onError:
(status,errorString,result)=>{
text_info.text = result
console.debug(result)
}
onSuccess:
(result)=>{
text_info.text = result
}
onUploadProgress:
(sent,total)=>{
var locale = Qt.locale()
var precent = (sent/total * 100).toFixed(0) + "%"
btn_upload.text = "上传中..."+precent
text_upload_file_size.text = "%1/%2".arg(locale.formattedDataSize(sent)).arg(locale.formattedDataSize(total))
layout_upload_file_size.visible = true
}
}
FileDialog { FileDialog {
id: file_dialog id: file_dialog
onAccepted: { onAccepted: {
@ -159,65 +223,46 @@ FluContentPage{
var filePath = FluTools.toLocalPath(fileUrl) var filePath = FluTools.toLocalPath(fileUrl)
param[fileName] = filePath param[fileName] = filePath
} }
console.debug(JSON.stringify(param)) http.upload("https://httpbingo.org/post",callable_upload,param)
var callable = {}
callable.onStart = function(){
btn_upload.disabled = true
}
callable.onFinish = function(){
btn_upload.disabled = false
btn_upload.text = "上传文件"
layout_upload_file_size.visible = false
text_upload_file_size.text = ""
}
callable.onSuccess = function(result){
text_info.text = result
console.debug(result)
}
callable.onError = function(status,errorString,result){
text_info.text = result
console.debug(result)
}
callable.onUploadProgress = function(sent,total){
var locale = Qt.locale()
var precent = (sent/total * 100).toFixed(0) + "%"
btn_upload.text = "上传中..."+precent
text_upload_file_size.text = "%1/%2".arg(locale.formattedDataSize(sent)).arg(locale.formattedDataSize(total))
layout_upload_file_size.visible = true
}
http.upload("https://httpbingo.org/post",callable,param)
} }
} }
FolderDialog { HttpCallable{
id: folder_dialog id:callable_download
currentFolder: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0] onStart: {
onAccepted: { btn_download.disabled = true
var callable = {} }
callable.onStart = function(){ onFinish: {
btn_download.disabled = true btn_download.disabled = false
btn_download.text = "下载文件"
layout_download_file_size.visible = false
text_download_file_size.text = ""
}
onError:
(status,errorString,result)=>{
showError(errorString)
console.debug(status+";"+errorString+";"+result)
} }
callable.onFinish = function(){ onSuccess:
btn_download.disabled = false (result)=>{
btn_download.text = "下载文件"
layout_download_file_size.visible = false
text_download_file_size.text = ""
}
callable.onSuccess = function(result){
showSuccess(result) showSuccess(result)
} }
callable.onError = function(status,errorString){ onDownloadProgress:
showError(errorString) (recv,total)=>{
}
callable.onDownloadProgress = function(recv,total){
var locale = Qt.locale() var locale = Qt.locale()
var precent = (recv/total * 100).toFixed(0) + "%" var precent = (recv/total * 100).toFixed(0) + "%"
btn_download.text = "下载中..."+precent btn_download.text = "下载中..."+precent
text_download_file_size.text = "%1/%2".arg(locale.formattedDataSize(recv)).arg(locale.formattedDataSize(total)) text_download_file_size.text = "%1/%2".arg(locale.formattedDataSize(recv)).arg(locale.formattedDataSize(total))
layout_download_file_size.visible = true layout_download_file_size.visible = true
} }
}
FolderDialog {
id: folder_dialog
currentFolder: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0]
onAccepted: {
var path = FluTools.toLocalPath(currentFolder)+ "/big_buck_bunny.mp4" var path = FluTools.toLocalPath(currentFolder)+ "/big_buck_bunny.mp4"
http.download("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4",callable,path) http.download("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4",callable_download,path)
} }
} }
@ -261,7 +306,6 @@ FluContentPage{
} }
} }
FluRectangle{ FluRectangle{
id:layout_upload_file_size id:layout_upload_file_size
radius: [4,4,4,4] radius: [4,4,4,4]

View File

@ -309,27 +309,33 @@ CustomWindow {
} }
} }
function checkUpdate(){
var callable = {} HttpCallable{
callable.onStart = function(){ id:callable
onStart: {
console.debug("satrt check update...") console.debug("satrt check update...")
} }
callable.onFinish = function(){ onFinish: {
console.debug("check update finish") console.debug("check update finish")
} }
callable.onSuccess = function(result){ onSuccess:
var data = JSON.parse(result) (result)=>{
console.debug("current version "+appInfo.version) var data = JSON.parse(result)
console.debug("new version "+data.tag_name) console.debug("current version "+appInfo.version)
if(data.tag_name !== appInfo.version){ console.debug("new version "+data.tag_name)
dialog_update.newVerson = data.tag_name if(data.tag_name !== appInfo.version){
dialog_update.body = data.body dialog_update.newVerson = data.tag_name
dialog_update.open() dialog_update.body = data.body
dialog_update.open()
}
} }
} onError:
callable.onError = function(status,errorString){ (status,errorString)=>{
console.debug(status+";"+errorString) console.debug(status+";"+errorString)
} }
}
function checkUpdate(){
http.get("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest",callable) http.get("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest",callable)
} }

View File

@ -11,14 +11,57 @@ import "../component"
FluContentPage{ FluContentPage{
title:"Http" title:"Http"
property string cacheDirPath: FluTools.getApplicationDirPath() + "/cache/http"
FluHttp{ FluHttp{
id:http id:http
} }
FluHttp{
id:http_cache_ifnonecacherequest
cacheMode:FluHttpType.IfNoneCacheRequest
cacheDir:cacheDirPath
}
FluHttp{
id:http_cache_requestfailedreadcache
cacheMode:FluHttpType.RequestFailedReadCache
cacheDir:cacheDirPath
}
FluHttp{
id:http_cache_firstcachethenrequest
cacheMode:FluHttpType.FirstCacheThenRequest
cacheDir:cacheDirPath
}
HttpCallable{
id:callable
onStart: {
showLoading()
}
onFinish: {
hideLoading()
}
onError:
(status,errorString,result)=>{
console.debug(status+";"+errorString+";"+result)
}
onSuccess:
(result)=>{
text_info.text = result
console.debug(result)
}
onCache:
(result)=>{
text_info.text = result
console.debug(result)
}
}
Flickable{ Flickable{
id:layout_flick id:layout_flick
width: 160 width: 200
clip: true clip: true
anchors{ anchors{
top: parent.top top: parent.top
@ -37,20 +80,6 @@ FluContentPage{
implicitHeight: 36 implicitHeight: 36
text: "Get请求" text: "Get请求"
onClicked: { onClicked: {
var callable = {}
callable.onStart = function(){
showLoading()
}
callable.onFinish = function(){
hideLoading()
}
callable.onSuccess = function(result){
text_info.text = result
console.debug(result)
}
callable.onError = function(status,errorString){
console.debug(status+";"+errorString)
}
http.get("https://httpbingo.org/get",callable) http.get("https://httpbingo.org/get",callable)
} }
} }
@ -59,20 +88,6 @@ FluContentPage{
implicitHeight: 36 implicitHeight: 36
text: "Post表单请求" text: "Post表单请求"
onClicked: { onClicked: {
var callable = {}
callable.onStart = function(){
showLoading()
}
callable.onFinish = function(){
hideLoading()
}
callable.onSuccess = function(result){
text_info.text = result
console.debug(result)
}
callable.onError = function(status,errorString){
console.debug(status+";"+errorString)
}
var param = {} var param = {}
param.custname = "朱子楚" param.custname = "朱子楚"
param.custtel = "1234567890" param.custtel = "1234567890"
@ -85,20 +100,6 @@ FluContentPage{
implicitHeight: 36 implicitHeight: 36
text: "Post Json请求" text: "Post Json请求"
onClicked: { onClicked: {
var callable = {}
callable.onStart = function(){
showLoading()
}
callable.onFinish = function(){
hideLoading()
}
callable.onSuccess = function(result){
text_info.text = result
console.debug(result)
}
callable.onError = function(status,errorString){
console.debug(status+";"+errorString)
}
var param = {} var param = {}
param.custname = "朱子楚" param.custname = "朱子楚"
param.custtel = "1234567890" param.custtel = "1234567890"
@ -111,20 +112,6 @@ FluContentPage{
implicitHeight: 36 implicitHeight: 36
text: "Post String请求" text: "Post String请求"
onClicked: { onClicked: {
var callable = {}
callable.onStart = function(){
showLoading()
}
callable.onFinish = function(){
hideLoading()
}
callable.onSuccess = function(result){
text_info.text = result
console.debug(result)
}
callable.onError = function(status,errorString){
console.debug(status+";"+errorString)
}
var param = "我命由我不由天" var param = "我命由我不由天"
http.postString("https://httpbingo.org/post",callable,param) http.postString("https://httpbingo.org/post",callable,param)
} }
@ -147,9 +134,86 @@ FluContentPage{
file_dialog.open() file_dialog.open()
} }
} }
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "FirstCacheThenRequest缓存"
onClicked: {
var param = {}
param.cacheMode = "FirstCacheThenRequest"
http_cache_firstcachethenrequest.post("https://httpbingo.org/post",callable,param)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "RequestFailedReadCache缓存"
onClicked: {
var param = {}
param.cacheMode = "RequestFailedReadCache"
http_cache_requestfailedreadcache.post("https://httpbingo.org/post",callable,param)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "IfNoneCacheRequest缓存"
onClicked: {
var param = {}
param.cacheMode = "IfNoneCacheRequest"
http_cache_ifnonecacherequest.post("https://httpbingo.org/post",callable,param)
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "删除缓存"
onClicked: {
console.debug(FluTools.removeDir(cacheDirPath))
}
}
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "清空右边数据"
onClicked: {
text_info.text = ""
}
}
} }
} }
HttpCallable{
id:callable_upload
onStart: {
btn_upload.disabled = true
}
onFinish: {
btn_upload.disabled = false
btn_upload.text = "上传文件"
layout_upload_file_size.visible = false
text_upload_file_size.text = ""
}
onError:
(status,errorString,result)=>{
text_info.text = result
console.debug(result)
}
onSuccess:
(result)=>{
text_info.text = result
}
onUploadProgress:
(sent,total)=>{
var locale = Qt.locale()
var precent = (sent/total * 100).toFixed(0) + "%"
btn_upload.text = "上传中..."+precent
text_upload_file_size.text = "%1/%2".arg(locale.formattedDataSize(sent)).arg(locale.formattedDataSize(total))
layout_upload_file_size.visible = true
}
}
FileDialog { FileDialog {
id: file_dialog id: file_dialog
onAccepted: { onAccepted: {
@ -160,65 +224,46 @@ FluContentPage{
var filePath = FluTools.toLocalPath(fileUrl) var filePath = FluTools.toLocalPath(fileUrl)
param[fileName] = filePath param[fileName] = filePath
} }
console.debug(JSON.stringify(param)) http.upload("https://httpbingo.org/post",callable_upload,param)
var callable = {}
callable.onStart = function(){
btn_upload.disabled = true
}
callable.onFinish = function(){
btn_upload.disabled = false
btn_upload.text = "上传文件"
layout_upload_file_size.visible = false
text_upload_file_size.text = ""
}
callable.onSuccess = function(result){
text_info.text = result
console.debug(result)
}
callable.onError = function(status,errorString,result){
text_info.text = result
console.debug(result)
}
callable.onUploadProgress = function(sent,total){
var locale = Qt.locale()
var precent = (sent/total * 100).toFixed(0) + "%"
btn_upload.text = "上传中..."+precent
text_upload_file_size.text = "%1/%2".arg(locale.formattedDataSize(sent)).arg(locale.formattedDataSize(total))
layout_upload_file_size.visible = true
}
http.upload("https://httpbingo.org/post",callable,param)
} }
} }
FolderDialog { HttpCallable{
id: folder_dialog id:callable_download
currentFolder: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0] onStart: {
onAccepted: { btn_download.disabled = true
var callable = {} }
callable.onStart = function(){ onFinish: {
btn_download.disabled = true btn_download.disabled = false
btn_download.text = "下载文件"
layout_download_file_size.visible = false
text_download_file_size.text = ""
}
onError:
(status,errorString,result)=>{
showError(errorString)
console.debug(status+";"+errorString+";"+result)
} }
callable.onFinish = function(){ onSuccess:
btn_download.disabled = false (result)=>{
btn_download.text = "下载文件"
layout_download_file_size.visible = false
text_download_file_size.text = ""
}
callable.onSuccess = function(result){
showSuccess(result) showSuccess(result)
} }
callable.onError = function(status,errorString){ onDownloadProgress:
showError(errorString) (recv,total)=>{
}
callable.onDownloadProgress = function(recv,total){
var locale = Qt.locale() var locale = Qt.locale()
var precent = (recv/total * 100).toFixed(0) + "%" var precent = (recv/total * 100).toFixed(0) + "%"
btn_download.text = "下载中..."+precent btn_download.text = "下载中..."+precent
text_download_file_size.text = "%1/%2".arg(locale.formattedDataSize(recv)).arg(locale.formattedDataSize(total)) text_download_file_size.text = "%1/%2".arg(locale.formattedDataSize(recv)).arg(locale.formattedDataSize(total))
layout_download_file_size.visible = true layout_download_file_size.visible = true
} }
}
FolderDialog {
id: folder_dialog
currentFolder: StandardPaths.standardLocations(StandardPaths.DownloadLocation)[0]
onAccepted: {
var path = FluTools.toLocalPath(currentFolder)+ "/big_buck_bunny.mp4" var path = FluTools.toLocalPath(currentFolder)+ "/big_buck_bunny.mp4"
http.download("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4",callable,path) http.download("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4",callable_download,path)
} }
} }
@ -262,7 +307,6 @@ FluContentPage{
} }
} }
FluRectangle{ FluRectangle{
id:layout_upload_file_size id:layout_upload_file_size
radius: [4,4,4,4] radius: [4,4,4,4]

View File

@ -310,27 +310,32 @@ CustomWindow {
} }
} }
function checkUpdate(){ HttpCallable{
var callable = {} id:callable
callable.onStart = function(){ onStart: {
console.debug("satrt check update...") console.debug("satrt check update...")
} }
callable.onFinish = function(){ onFinish: {
console.debug("check update finish") console.debug("check update finish")
} }
callable.onSuccess = function(result){ onSuccess:
var data = JSON.parse(result) (result)=>{
console.debug("current version "+appInfo.version) var data = JSON.parse(result)
console.debug("new version "+data.tag_name) console.debug("current version "+appInfo.version)
if(data.tag_name !== appInfo.version){ console.debug("new version "+data.tag_name)
dialog_update.newVerson = data.tag_name if(data.tag_name !== appInfo.version){
dialog_update.body = data.body dialog_update.newVerson = data.tag_name
dialog_update.open() dialog_update.body = data.body
dialog_update.open()
}
} }
} onError:
callable.onError = function(status,errorString){ (status,errorString)=>{
console.debug(status+";"+errorString) console.debug(status+";"+errorString)
} }
}
function checkUpdate(){
http.get("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest",callable) http.get("https://api.github.com/repos/zhuzichu520/FluentUI/releases/latest",callable)
} }

View File

@ -4,6 +4,24 @@
#include <QObject> #include <QObject>
#include <QtQml/qqml.h> #include <QtQml/qqml.h>
namespace FluHttpType {
Q_NAMESPACE
enum CacheMode {
/** 不使用缓存 */
NoCache = 0x0000,
/** 请求网络失败后,读取缓存 */
RequestFailedReadCache = 0x0001,
/** 如果缓存不存在才请求网络,否则使用缓存 */
IfNoneCacheRequest = 0x0002,
/** 先使用缓存,不管是否存在,仍然请求网络 */
FirstCacheThenRequest = 0x0004,
};
Q_ENUM_NS(CacheMode)
QML_NAMED_ELEMENT(FluHttpType)
}
namespace FluScreenshotType { namespace FluScreenshotType {
Q_NAMESPACE Q_NAMESPACE

View File

@ -6,14 +6,26 @@
#include <QUrlQuery> #include <QUrlQuery>
#include <QHttpMultiPart> #include <QHttpMultiPart>
#include <QJsonDocument> #include <QJsonDocument>
#include <QStandardPaths>
#include <QTextStream>
#include <QDir>
#include "Def.h"
#include "MainThread.h" #include "MainThread.h"
#include "FluApp.h" #include "FluApp.h"
#include "FluTools.h"
HttpCallable::HttpCallable(QObject *parent)
: QObject{parent}
{
}
FluHttp::FluHttp(QObject *parent) FluHttp::FluHttp(QObject *parent)
: QObject{parent} : QObject{parent}
{ {
retry(3); retry(3);
timeout(15000); timeout(15000);
cacheMode(FluHttpType::CacheMode::NoCache);
cacheDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)+"/httpcache");
} }
FluHttp::~FluHttp(){ FluHttp::~FluHttp(){
@ -21,7 +33,7 @@ FluHttp::~FluHttp(){
} }
void FluHttp::cancel(){ void FluHttp::cancel(){
foreach (QPointer<QNetworkReply> item, _cache) { foreach (QPointer<QNetworkReply> item, _cacheReply) {
if(item){ if(item){
item->abort(); item->abort();
} }
@ -29,13 +41,22 @@ void FluHttp::cancel(){
} }
void FluHttp::handleReply(QNetworkReply* reply){ void FluHttp::handleReply(QNetworkReply* reply){
_cache.append(reply); _cacheReply.append(reply);
} }
void FluHttp::post(QString url,QJSValue callable,QMap<QString, QVariant> params,QMap<QString, QVariant> headers){ void FluHttp::post(QString url,HttpCallable* callable,QMap<QString, QVariant> params,QMap<QString, QVariant> headers){
QMap<QString, QVariant> data = invokeIntercept(params,headers,"post").toMap();
QThreadPool::globalInstance()->start([=](){ QThreadPool::globalInstance()->start([=](){
onStart(callable); auto requestMap = toRequest(url,params,headers,"post");
QMap<QString, QVariant> data = invokeIntercept(requestMap).toMap();
Q_EMIT callable->start();
if(_cacheMode == FluHttpType::CacheMode::IfNoneCacheRequest && cacheExists(requestMap)){
Q_EMIT callable->cache(readCache(requestMap));
Q_EMIT callable->finish();
return;
}
if(_cacheMode == FluHttpType::CacheMode::FirstCacheThenRequest){
Q_EMIT callable->cache(readCache(requestMap));
}
for (int i = 0; i < retry(); ++i) { for (int i = 0; i < retry(); ++i) {
QNetworkAccessManager manager; QNetworkAccessManager manager;
manager.setTransferTimeout(timeout()); manager.setTransferTimeout(timeout());
@ -55,7 +76,7 @@ void FluHttp::post(QString url,QJSValue callable,QMap<QString, QVariant> params,
} }
QEventLoop loop; QEventLoop loop;
QNetworkReply* reply = manager.post(request,&multiPart); QNetworkReply* reply = manager.post(request,&multiPart);
_cache.append(reply); _cacheReply.append(reply);
connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){ connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){
loop.quit(); loop.quit();
}); });
@ -64,26 +85,40 @@ void FluHttp::post(QString url,QJSValue callable,QMap<QString, QVariant> params,
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString errorString = reply->errorString(); QString errorString = reply->errorString();
bool isSuccess = reply->error() == QNetworkReply::NoError; bool isSuccess = reply->error() == QNetworkReply::NoError;
_cache.removeOne(reply); _cacheReply.removeOne(reply);
reply->deleteLater(); reply->deleteLater();
reply = nullptr; reply = nullptr;
if (isSuccess) { if (isSuccess) {
onSuccess(callable,result); handleCache(requestMap,result);
Q_EMIT callable->success(result);
break; break;
}else{ }else{
if(i == retry()-1){ if(i == retry()-1){
onError(callable,status,errorString,result); if(_cacheMode == FluHttpType::CacheMode::RequestFailedReadCache){
Q_EMIT callable->cache(readCache(requestMap));
}
Q_EMIT callable->error(status,errorString,result);
} }
} }
} }
onFinish(callable); Q_EMIT callable->finish();
// Q_EMIT callable->finish();
}); });
} }
void FluHttp::postString(QString url,QJSValue callable,QString params,QMap<QString, QVariant> headers){ void FluHttp::postString(QString url,HttpCallable* callable,QString params,QMap<QString, QVariant> headers){
QMap<QString, QVariant> data = invokeIntercept(params,headers,"postString").toMap();
QThreadPool::globalInstance()->start([=](){ QThreadPool::globalInstance()->start([=](){
onStart(callable); auto requestMap = toRequest(url,params,headers,"postString");
QMap<QString, QVariant> data = invokeIntercept(requestMap).toMap();
Q_EMIT callable->start();
if(_cacheMode == FluHttpType::CacheMode::IfNoneCacheRequest && cacheExists(requestMap)){
Q_EMIT callable->cache(readCache(requestMap));
Q_EMIT callable->finish();
return;
}
if(_cacheMode == FluHttpType::CacheMode::FirstCacheThenRequest){
Q_EMIT callable->cache(readCache(requestMap));
}
for (int i = 0; i < retry(); ++i) { for (int i = 0; i < retry(); ++i) {
QNetworkAccessManager manager; QNetworkAccessManager manager;
manager.setTransferTimeout(timeout()); manager.setTransferTimeout(timeout());
@ -94,7 +129,7 @@ void FluHttp::postString(QString url,QJSValue callable,QString params,QMap<QStri
request.setHeader(QNetworkRequest::ContentTypeHeader, contentType); request.setHeader(QNetworkRequest::ContentTypeHeader, contentType);
QEventLoop loop; QEventLoop loop;
QNetworkReply* reply = manager.post(request,params.toUtf8()); QNetworkReply* reply = manager.post(request,params.toUtf8());
_cache.append(reply); _cacheReply.append(reply);
connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){ connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){
loop.quit(); loop.quit();
}); });
@ -103,26 +138,39 @@ void FluHttp::postString(QString url,QJSValue callable,QString params,QMap<QStri
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString errorString = reply->errorString(); QString errorString = reply->errorString();
bool isSuccess = reply->error() == QNetworkReply::NoError; bool isSuccess = reply->error() == QNetworkReply::NoError;
_cache.removeOne(reply); _cacheReply.removeOne(reply);
reply->deleteLater(); reply->deleteLater();
reply = nullptr; reply = nullptr;
if (isSuccess) { if (isSuccess) {
onSuccess(callable,result); handleCache(requestMap,result);
Q_EMIT callable->success(result);
break; break;
}else{ }else{
if(i == retry()-1){ if(i == retry()-1){
onError(callable,status,errorString,result); if(_cacheMode == FluHttpType::CacheMode::RequestFailedReadCache){
Q_EMIT callable->cache(readCache(requestMap));
}
Q_EMIT callable->error(status,errorString,result);
} }
} }
} }
onFinish(callable); Q_EMIT callable->finish();
}); });
} }
void FluHttp::postJson(QString url,QJSValue callable,QMap<QString, QVariant> params,QMap<QString, QVariant> headers){ void FluHttp::postJson(QString url,HttpCallable* callable,QMap<QString, QVariant> params,QMap<QString, QVariant> headers){
QMap<QString, QVariant> data = invokeIntercept(params,headers,"postJson").toMap();
QThreadPool::globalInstance()->start([=](){ QThreadPool::globalInstance()->start([=](){
onStart(callable); auto requestMap = toRequest(url,params,headers,"postJson");
QMap<QString, QVariant> data = invokeIntercept(requestMap).toMap();
Q_EMIT callable->start();
if(_cacheMode == FluHttpType::CacheMode::IfNoneCacheRequest && cacheExists(requestMap)){
Q_EMIT callable->cache(readCache(requestMap));
Q_EMIT callable->finish();
return;
}
if(_cacheMode == FluHttpType::CacheMode::FirstCacheThenRequest){
Q_EMIT callable->cache(readCache(requestMap));
}
for (int i = 0; i < retry(); ++i) { for (int i = 0; i < retry(); ++i) {
QNetworkAccessManager manager; QNetworkAccessManager manager;
manager.setTransferTimeout(timeout()); manager.setTransferTimeout(timeout());
@ -133,7 +181,7 @@ void FluHttp::postJson(QString url,QJSValue callable,QMap<QString, QVariant> par
request.setHeader(QNetworkRequest::ContentTypeHeader, contentType); request.setHeader(QNetworkRequest::ContentTypeHeader, contentType);
QEventLoop loop; QEventLoop loop;
QNetworkReply* reply = manager.post(request,QJsonDocument::fromVariant(data["params"]).toJson()); QNetworkReply* reply = manager.post(request,QJsonDocument::fromVariant(data["params"]).toJson());
_cache.append(reply); _cacheReply.append(reply);
connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){ connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){
loop.quit(); loop.quit();
}); });
@ -142,27 +190,40 @@ void FluHttp::postJson(QString url,QJSValue callable,QMap<QString, QVariant> par
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString errorString = reply->errorString(); QString errorString = reply->errorString();
bool isSuccess = reply->error() == QNetworkReply::NoError; bool isSuccess = reply->error() == QNetworkReply::NoError;
_cache.removeOne(reply); _cacheReply.removeOne(reply);
reply->deleteLater(); reply->deleteLater();
reply = nullptr; reply = nullptr;
if (isSuccess) { if (isSuccess) {
onSuccess(callable,result); handleCache(requestMap,result);
Q_EMIT callable->success(result);
break; break;
}else{ }else{
if(i == retry()-1){ if(i == retry()-1){
onError(callable,status,errorString,result); if(_cacheMode == FluHttpType::CacheMode::RequestFailedReadCache){
Q_EMIT callable->cache(readCache(requestMap));
}
Q_EMIT callable->error(status,errorString,result);
} }
} }
} }
onFinish(callable); Q_EMIT callable->finish();
}); });
} }
void FluHttp::get(QString url,QJSValue callable,QMap<QString, QVariant> params,QMap<QString, QVariant> headers){ void FluHttp::get(QString url,HttpCallable* callable,QMap<QString, QVariant> params,QMap<QString, QVariant> headers){
QMap<QString, QVariant> data = invokeIntercept(params,headers,"get").toMap();
QThreadPool::globalInstance()->start([=](){ QThreadPool::globalInstance()->start([=](){
auto requestMap = toRequest(url,params,headers,"get");
QMap<QString, QVariant> data = invokeIntercept(requestMap).toMap();
Q_EMIT callable->start();
if(_cacheMode == FluHttpType::CacheMode::FirstCacheThenRequest){
Q_EMIT callable->cache(readCache(requestMap));
}
if(_cacheMode == FluHttpType::CacheMode::IfNoneCacheRequest && cacheExists(requestMap)){
Q_EMIT callable->cache(readCache(requestMap));
Q_EMIT callable->finish();
return;
}
for (int i = 0; i < retry(); ++i) { for (int i = 0; i < retry(); ++i) {
onStart(callable);
QNetworkAccessManager manager; QNetworkAccessManager manager;
manager.setTransferTimeout(timeout()); manager.setTransferTimeout(timeout());
QUrl _url(url); QUrl _url(url);
@ -171,7 +232,7 @@ void FluHttp::get(QString url,QJSValue callable,QMap<QString, QVariant> params,Q
addHeaders(&request,data["headers"].toMap()); addHeaders(&request,data["headers"].toMap());
QEventLoop loop; QEventLoop loop;
QNetworkReply* reply = manager.get(request); QNetworkReply* reply = manager.get(request);
_cache.append(reply); _cacheReply.append(reply);
connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){ connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){
loop.quit(); loop.quit();
}); });
@ -180,26 +241,31 @@ void FluHttp::get(QString url,QJSValue callable,QMap<QString, QVariant> params,Q
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString errorString = reply->errorString(); QString errorString = reply->errorString();
bool isSuccess = reply->error() == QNetworkReply::NoError; bool isSuccess = reply->error() == QNetworkReply::NoError;
_cache.removeOne(reply); _cacheReply.removeOne(reply);
reply->deleteLater(); reply->deleteLater();
reply = nullptr; reply = nullptr;
if (isSuccess) { if (isSuccess) {
onSuccess(callable,result); handleCache(requestMap,result);
Q_EMIT callable->success(result);
break; break;
}else{ }else{
if(i == retry()-1){ if(i == retry()-1){
onError(callable,status,errorString,result); if(_cacheMode == FluHttpType::CacheMode::RequestFailedReadCache){
Q_EMIT callable->cache(readCache(requestMap));
}
Q_EMIT callable->error(status,errorString,result);
} }
} }
} }
onFinish(callable); Q_EMIT callable->finish();
}); });
} }
void FluHttp::download(QString url,QJSValue callable,QString filePath,QMap<QString, QVariant> params,QMap<QString, QVariant> headers){ void FluHttp::download(QString url,HttpCallable* callable,QString filePath,QMap<QString, QVariant> params,QMap<QString, QVariant> headers){
QMap<QString, QVariant> data = invokeIntercept(params,headers,"download").toMap();
QThreadPool::globalInstance()->start([=](){ QThreadPool::globalInstance()->start([=](){
onStart(callable); auto requestMap = toRequest(url,params,headers,"download");
QMap<QString, QVariant> data = invokeIntercept(requestMap).toMap();
Q_EMIT callable->start();
QNetworkAccessManager manager; QNetworkAccessManager manager;
QUrl _url(url); QUrl _url(url);
addQueryParam(&_url,data["params"].toMap()); addQueryParam(&_url,data["params"].toMap());
@ -209,8 +275,8 @@ void FluHttp::download(QString url,QJSValue callable,QString filePath,QMap<QStri
QIODevice::OpenMode mode = QIODevice::WriteOnly|QIODevice::Truncate; QIODevice::OpenMode mode = QIODevice::WriteOnly|QIODevice::Truncate;
if (!file->open(mode)) if (!file->open(mode))
{ {
onError(callable,-1,QString("Url: %1 %2 Non-Writable").arg(request.url().toString(),file->fileName()),""); Q_EMIT callable->error(-1,QString("Url: %1 %2 Non-Writable").arg(request.url().toString(),file->fileName()),"");
onFinish(callable); Q_EMIT callable->finish();
return; return;
} }
QEventLoop loop; QEventLoop loop;
@ -218,28 +284,29 @@ void FluHttp::download(QString url,QJSValue callable,QString filePath,QMap<QStri
loop.quit(); loop.quit();
}); });
QPointer<QNetworkReply> reply = manager.get(request); QPointer<QNetworkReply> reply = manager.get(request);
_cache.append(reply); _cacheReply.append(reply);
connect(reply,&QNetworkReply::downloadProgress,this,[=](qint64 bytesReceived, qint64 bytesTotal){ connect(reply,&QNetworkReply::downloadProgress,this,[=](qint64 bytesReceived, qint64 bytesTotal){
onDownloadProgress(callable,bytesReceived,bytesTotal); Q_EMIT callable->downloadProgress(bytesReceived,bytesTotal);
}); });
loop.exec(); loop.exec();
if (reply->error() == QNetworkReply::NoError) { if (reply->error() == QNetworkReply::NoError) {
file->write(reply->readAll()); file->write(reply->readAll());
onSuccess(callable,filePath); Q_EMIT callable->success(filePath);
}else{ }else{
onError(callable,reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(),reply->errorString(),""); Q_EMIT callable->error(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(),reply->errorString(),"");
} }
_cache.removeOne(reply); _cacheReply.removeOne(reply);
reply->deleteLater(); reply->deleteLater();
reply = nullptr; reply = nullptr;
onFinish(callable); Q_EMIT callable->finish();
}); });
} }
void FluHttp::upload(QString url,QJSValue callable,QMap<QString, QVariant> params,QMap<QString, QVariant> headers){ void FluHttp::upload(QString url,HttpCallable* callable,QMap<QString, QVariant> params,QMap<QString, QVariant> headers){
QMap<QString, QVariant> data = invokeIntercept(params,headers,"upload").toMap();
QThreadPool::globalInstance()->start([=](){ QThreadPool::globalInstance()->start([=](){
onStart(callable); auto requestMap = toRequest(url,params,headers,"upload");
QMap<QString, QVariant> data = invokeIntercept(requestMap).toMap();
Q_EMIT callable->start();
QNetworkAccessManager manager; QNetworkAccessManager manager;
manager.setTransferTimeout(timeout()); manager.setTransferTimeout(timeout());
QUrl _url(url); QUrl _url(url);
@ -262,41 +329,46 @@ void FluHttp::upload(QString url,QJSValue callable,QMap<QString, QVariant> param
} }
QEventLoop loop; QEventLoop loop;
QNetworkReply* reply = manager.post(request,&multiPart); QNetworkReply* reply = manager.post(request,&multiPart);
_cache.append(reply); _cacheReply.append(reply);
connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){ connect(&manager,&QNetworkAccessManager::finished,this,[&loop](QNetworkReply *reply){
loop.quit(); loop.quit();
}); });
connect(reply,&QNetworkReply::uploadProgress,this,[=](qint64 bytesSent, qint64 bytesTotal){ connect(reply,&QNetworkReply::uploadProgress,this,[=](qint64 bytesSent, qint64 bytesTotal){
onUploadProgress(callable,bytesSent,bytesTotal); Q_EMIT callable->uploadProgress(bytesSent,bytesTotal);
}); });
loop.exec(); loop.exec();
QString result = QString::fromUtf8(reply->readAll()); QString result = QString::fromUtf8(reply->readAll());
int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
QString errorString = reply->errorString(); QString errorString = reply->errorString();
bool isSuccess = reply->error() == QNetworkReply::NoError; bool isSuccess = reply->error() == QNetworkReply::NoError;
_cache.removeOne(reply); _cacheReply.removeOne(reply);
reply->deleteLater(); reply->deleteLater();
reply = nullptr; reply = nullptr;
if (isSuccess) { if (isSuccess) {
onSuccess(callable,result); Q_EMIT callable->success(result);
}else{ }else{
onError(callable,status,errorString,result); Q_EMIT callable->error(status,errorString,result);
} }
onFinish(callable); Q_EMIT callable->finish();
}); });
} }
QVariant FluHttp::invokeIntercept(const QVariant& params,const QVariant& headers,const QString& method){ QMap<QString, QVariant> FluHttp::toRequest(const QString& url,const QVariant& params,const QVariant& headers,const QString& method){
QMap<QString, QVariant> requet = { QMap<QString, QVariant> request = {
{"url",url},
{"params",params}, {"params",params},
{"headers",headers}, {"headers",headers},
{"method",method} {"method",method}
}; };
return request;
}
QVariant FluHttp::invokeIntercept(QMap<QString, QVariant> request){
if(!FluApp::getInstance()->httpInterceptor()){ if(!FluApp::getInstance()->httpInterceptor()){
return requet; return request;
} }
QVariant target; QVariant target;
QMetaObject::invokeMethod(FluApp::getInstance()->httpInterceptor(), "onIntercept",Q_RETURN_ARG(QVariant,target),Q_ARG(QVariant, requet)); QMetaObject::invokeMethod(FluApp::getInstance()->httpInterceptor(), "onIntercept",Qt::BlockingQueuedConnection,Q_RETURN_ARG(QVariant,target),Q_ARG(QVariant, request));
return target; return target;
} }
@ -320,54 +392,44 @@ void FluHttp::addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>&
} }
} }
void FluHttp::onStart(const QJSValue& callable){ QString FluHttp::readCache(const QMap<QString, QVariant>& request){
MainThread::post([=](){ auto filePath = getCacheFilePath(request);
QJSValue onStart = callable.property("onStart"); QString result;
onStart.call(); QFile file(filePath);
}); if(!file.exists()){
return result;
}
if (file.open(QIODevice::ReadOnly)) {
QTextStream stream(&file);
result = FluTools::getInstance()->fromBase64(stream.readAll().toUtf8());
}
return result;
} }
void FluHttp::onFinish(const QJSValue& callable){ bool FluHttp::cacheExists(const QMap<QString, QVariant>& request){
MainThread::post([=](){ return QFile(getCacheFilePath(request)).exists();
QJSValue onFinish = callable.property("onFinish");
onFinish.call();
});
} }
void FluHttp::onError(const QJSValue& callable,int status,QString errorString,QString result){ QString FluHttp::getCacheFilePath(const QMap<QString, QVariant>& request){
MainThread::post([=](){ auto fileName = FluTools::getInstance()->md5(QJsonDocument::fromVariant(QVariant(request)).toJson());
QJSValue onError = callable.property("onError"); QDir dir = _cacheDir;
QJSValueList args; if (!dir.exists(_cacheDir)){
args<<status<<errorString<<result; dir.mkpath(_cacheDir);
onError.call(args); }
}); auto filePath = _cacheDir+"/"+fileName;
return filePath;
} }
void FluHttp::onSuccess(const QJSValue& callable,QString result){ void FluHttp::handleCache(QMap<QString, QVariant> request,const QString& result){
MainThread::post([=](){ if(_cacheMode==FluHttpType::CacheMode::NoCache){
QJSValueList args; return;
args<<result; }
QJSValue onSuccess = callable.property("onSuccess"); auto filePath = getCacheFilePath(request);
onSuccess.call(args); QSharedPointer<QFile> file(new QFile(filePath));
}); QIODevice::OpenMode mode = QIODevice::WriteOnly|QIODevice::Truncate;
} if (!file->open(mode))
{
void FluHttp::onDownloadProgress(const QJSValue& callable,qint64 recv, qint64 total){ return;
MainThread::post([=](){ }
QJSValueList args; file->write(FluTools::getInstance()->toBase64(result).toUtf8());
args<<static_cast<double>(recv);
args<<static_cast<double>(total);
QJSValue onDownloadProgress = callable.property("onDownloadProgress");
onDownloadProgress.call(args);
});
}
void FluHttp::onUploadProgress(const QJSValue& callable,qint64 sent, qint64 total){
MainThread::post([=](){
QJSValueList args;
args<<static_cast<double>(sent);
args<<static_cast<double>(total);
QJSValue onUploadProgress = callable.property("onUploadProgress");
onUploadProgress.call(args);
});
} }

View File

@ -6,37 +6,53 @@
#include <QFile> #include <QFile>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include "stdafx.h" #include "stdafx.h"
#include <QMutex>
class HttpCallable : public QObject{
Q_OBJECT
QML_NAMED_ELEMENT(HttpCallable)
public:
explicit HttpCallable(QObject *parent = nullptr);
Q_SIGNAL void start();
Q_SIGNAL void finish();
Q_SIGNAL void error(int status,QString errorString,QString result);
Q_SIGNAL void success(QString result);
Q_SIGNAL void cache(QString result);
Q_SIGNAL void downloadProgress(qint64 recv, qint64 total);
Q_SIGNAL void uploadProgress(qint64 recv, qint64 total);
};
class FluHttp : public QObject class FluHttp : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY_AUTO(int,retry); Q_PROPERTY_AUTO(int,retry);
Q_PROPERTY_AUTO(int,timeout) Q_PROPERTY_AUTO(int,timeout)
Q_PROPERTY_AUTO(int,cacheMode);
Q_PROPERTY_AUTO(QString,cacheDir);
QML_NAMED_ELEMENT(FluHttp) QML_NAMED_ELEMENT(FluHttp)
private: private:
QVariant invokeIntercept(const QVariant& params,const QVariant& headers,const QString& method); QVariant invokeIntercept(QMap<QString, QVariant> request);
QMap<QString, QVariant> toRequest(const QString& url,const QVariant& params,const QVariant& headers,const QString& method);
void handleReply(QNetworkReply* reply); void handleReply(QNetworkReply* reply);
void addQueryParam(QUrl* url,const QMap<QString, QVariant>& params); void addQueryParam(QUrl* url,const QMap<QString, QVariant>& params);
void addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>& params); void addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>& params);
void onStart(const QJSValue& callable); void handleCache(QMap<QString, QVariant> request, const QString& result);
void onFinish(const QJSValue& callable); QString readCache(const QMap<QString, QVariant>& request);
void onError(const QJSValue& callable,int status,QString errorString,QString result); bool cacheExists(const QMap<QString, QVariant>& request);
void onSuccess(const QJSValue& callable,QString result); QString getCacheFilePath(const QMap<QString, QVariant>& request);
void onDownloadProgress(const QJSValue& callable,qint64 recv, qint64 total);
void onUploadProgress(const QJSValue& callable,qint64 recv, qint64 total);
public: public:
explicit FluHttp(QObject *parent = nullptr); explicit FluHttp(QObject *parent = nullptr);
~FluHttp(); ~FluHttp();
//神坑!!! 如果参数使用QVariantMap会有问题在6.4.3版本中QML一调用就会编译失败。所以改用QMap<QString, QVariant> //神坑!!! 如果参数使用QVariantMap会有问题在6.4.3版本中QML一调用就会编译失败。所以改用QMap<QString, QVariant>
Q_INVOKABLE void get(QString url,QJSValue callable,QMap<QString, QVariant> params= {},QMap<QString, QVariant> headers = {}); Q_INVOKABLE void get(QString url,HttpCallable* callable,QMap<QString, QVariant> params= {},QMap<QString, QVariant> headers = {});
Q_INVOKABLE void post(QString url,QJSValue callable,QMap<QString, QVariant> params= {},QMap<QString, QVariant> headers = {}); Q_INVOKABLE void post(QString url,HttpCallable* callable,QMap<QString, QVariant> params= {},QMap<QString, QVariant> headers = {});
Q_INVOKABLE void postString(QString url,QJSValue callable,QString params = "",QMap<QString, QVariant> headers = {}); Q_INVOKABLE void postString(QString url,HttpCallable* callable,QString params = "",QMap<QString, QVariant> headers = {});
Q_INVOKABLE void postJson(QString url,QJSValue callable,QMap<QString, QVariant> params = {},QMap<QString, QVariant> headers = {}); Q_INVOKABLE void postJson(QString url,HttpCallable* callable,QMap<QString, QVariant> params = {},QMap<QString, QVariant> headers = {});
Q_INVOKABLE void download(QString url,QJSValue callable,QString filePath,QMap<QString, QVariant> params = {},QMap<QString, QVariant> headers = {}); Q_INVOKABLE void download(QString url,HttpCallable* callable,QString filePath,QMap<QString, QVariant> params = {},QMap<QString, QVariant> headers = {});
Q_INVOKABLE void upload(QString url,QJSValue callable,QMap<QString, QVariant> params = {},QMap<QString, QVariant> headers = {}); Q_INVOKABLE void upload(QString url,HttpCallable* callable,QMap<QString, QVariant> params = {},QMap<QString, QVariant> headers = {});
Q_INVOKABLE void cancel(); Q_INVOKABLE void cancel();
private: private:
QList<QPointer<QNetworkReply>> _cache; QList<QPointer<QNetworkReply>> _cacheReply;
}; };
#endif // FLUHTTP_H #endif // FLUHTTP_H

View File

@ -31,7 +31,7 @@ FluTheme::FluTheme(QObject *parent)
}); });
primaryColor(FluColors::getInstance()->Blue()); primaryColor(FluColors::getInstance()->Blue());
nativeText(false); nativeText(false);
enableAnimation(false); enableAnimation(true);
darkMode(FluThemeType::DarkMode::Light); darkMode(FluThemeType::DarkMode::Light);
_systemDark = systemDark(); _systemDark = systemDark();
qApp->installEventFilter(this); qApp->installEventFilter(this);

View File

@ -6,6 +6,8 @@
#include <QScreen> #include <QScreen>
#include <QColor> #include <QColor>
#include <QFileInfo> #include <QFileInfo>
#include <QDir>
#include <QCryptographicHash>
#include <QTextDocument> #include <QTextDocument>
FluTools* FluTools::m_instance = nullptr; FluTools* FluTools::m_instance = nullptr;
@ -128,3 +130,23 @@ QUrl FluTools::getUrlByFilePath(const QString& path){
QColor FluTools::colorAlpha(const QColor& color,qreal alpha){ QColor FluTools::colorAlpha(const QColor& color,qreal alpha){
return QColor(color.red(),color.green(),color.blue(),255*alpha); return QColor(color.red(),color.green(),color.blue(),255*alpha);
} }
QString FluTools::md5(QString text)
{
return QCryptographicHash::hash(text.toUtf8(), QCryptographicHash::Md5).toHex();
}
QString FluTools::toBase64(QString text)
{
return text.toUtf8().toBase64();
}
QString FluTools::fromBase64(QString text)
{
return QByteArray::fromBase64(text.toUtf8());
}
bool FluTools::removeDir(QString dirPath){
QDir qDir(dirPath);
return qDir.removeRecursively();
}

View File

@ -144,6 +144,35 @@ public:
*/ */
Q_INVOKABLE QColor colorAlpha(const QColor&,qreal alpha); Q_INVOKABLE QColor colorAlpha(const QColor&,qreal alpha);
/**
* @brief md5
* @param text
* @return
*/
Q_INVOKABLE QString md5(QString text);
/**
* @brief toBase64
* @param text
* @return
*/
Q_INVOKABLE QString toBase64(QString text);
/**
* @brief fromBase64
* @param text
* @return
*/
Q_INVOKABLE QString fromBase64(QString text);
/**
* @brief removeDir
* @param dirPath
* @return
*/
Q_INVOKABLE bool removeDir(QString dirPath);
}; };
#endif // FLUTOOLS_H #endif // FLUTOOLS_H

View File

@ -752,7 +752,12 @@ Item {
id:nav_stack2 id:nav_stack2
anchors.fill: nav_stack anchors.fill: nav_stack
clip: true clip: true
visible: FluPageType.SingleInstance === nav_stack.currentItem.launchMode visible: {
if(!nav_stack.currentItem){
return false
}
return FluPageType.SingleInstance === nav_stack.currentItem.launchMode
}
} }
function navStack(){ function navStack(){
return nav_stack return nav_stack

View File

@ -96,24 +96,22 @@ Popup{
ctx.globalCompositeOperation = 'destination-out' ctx.globalCompositeOperation = 'destination-out'
ctx.fillStyle = 'black' ctx.fillStyle = 'black'
var rect = Qt.rect(d.pos.x-control.targetMargins,d.pos.y-control.targetMargins, d.target.width+control.targetMargins*2, d.target.height+control.targetMargins*2) var rect = Qt.rect(d.pos.x-control.targetMargins,d.pos.y-control.targetMargins, d.target.width+control.targetMargins*2, d.target.height+control.targetMargins*2)
ctx.fillRect(rect.x,rect.y,rect.width,rect.height) drawRoundedRect(rect,2,ctx)
ctx.restore() ctx.restore()
} }
//Todo
function drawRoundedRect(rect, r, ctx) { function drawRoundedRect(rect, r, ctx) {
var ptA = Qt.point(rect.x + r, rect.y) ctx.beginPath();
var ptB = Qt.point(rect.x + rect.width, rect.y) ctx.moveTo(rect.x + r, rect.y);
var ptC = Qt.point(rect.x + rect.width, rect.y + rect.height) ctx.lineTo(rect.x + rect.width - r, rect.y);
var ptD = Qt.point(rect.x, rect.y + rect.height) ctx.arcTo(rect.x + rect.width, rect.y, rect.x + rect.width, rect.y + r, r);
var ptE = Qt.point(rect.x, rect.y) ctx.lineTo(rect.x + rect.width, rect.y + rect.height - r);
ctx.beginPath() ctx.arcTo(rect.x + rect.width, rect.y + rect.height, rect.x + rect.width - r, rect.y + rect.height, r);
ctx.moveTo(ptA.x, ptA.y) ctx.lineTo(rect.x + r, rect.y + rect.height);
ctx.arcTo(ptB.x, ptB.y, ptC.x, ptC.y, r) ctx.arcTo(rect.x, rect.y + rect.height, rect.x, rect.y + rect.height - r, r);
ctx.arcTo(ptC.x, ptC.y, ptD.x, ptD.y, r) ctx.lineTo(rect.x, rect.y + r);
ctx.arcTo(ptD.x, ptD.y, ptE.x, ptE.y, r) ctx.arcTo(rect.x, rect.y, rect.x + r, rect.y, r);
ctx.arcTo(ptE.x, ptE.y, ptA.x, ptA.y, r) ctx.closePath();
ctx.fill() ctx.fill()
ctx.closePath()
} }
} }
FluArea{ FluArea{

View File

@ -753,7 +753,12 @@ Item {
id:nav_stack2 id:nav_stack2
anchors.fill: nav_stack anchors.fill: nav_stack
clip: true clip: true
visible: FluPageType.SingleInstance === nav_stack.currentItem.launchMode visible: {
if(!nav_stack.currentItem){
return false
}
return FluPageType.SingleInstance === nav_stack.currentItem.launchMode
}
} }
function navStack(){ function navStack(){
return nav_stack return nav_stack

View File

@ -89,19 +89,18 @@ Popup{
ctx.restore() ctx.restore()
} }
function drawRoundedRect(rect, r, ctx) { function drawRoundedRect(rect, r, ctx) {
var ptA = Qt.point(rect.x + r, rect.y) ctx.beginPath();
var ptB = Qt.point(rect.x + rect.width, rect.y) ctx.moveTo(rect.x + r, rect.y);
var ptC = Qt.point(rect.x + rect.width, rect.y + rect.height) ctx.lineTo(rect.x + rect.width - r, rect.y);
var ptD = Qt.point(rect.x, rect.y + rect.height) ctx.arcTo(rect.x + rect.width, rect.y, rect.x + rect.width, rect.y + r, r);
var ptE = Qt.point(rect.x, rect.y) ctx.lineTo(rect.x + rect.width, rect.y + rect.height - r);
ctx.beginPath() ctx.arcTo(rect.x + rect.width, rect.y + rect.height, rect.x + rect.width - r, rect.y + rect.height, r);
ctx.moveTo(ptA.x, ptA.y) ctx.lineTo(rect.x + r, rect.y + rect.height);
ctx.arcTo(ptB.x, ptB.y, ptC.x, ptC.y, r) ctx.arcTo(rect.x, rect.y + rect.height, rect.x, rect.y + rect.height - r, r);
ctx.arcTo(ptC.x, ptC.y, ptD.x, ptD.y, r) ctx.lineTo(rect.x, rect.y + r);
ctx.arcTo(ptD.x, ptD.y, ptE.x, ptE.y, r) ctx.arcTo(rect.x, rect.y, rect.x + r, rect.y, r);
ctx.arcTo(ptE.x, ptE.y, ptA.x, ptA.y, r) ctx.closePath();
ctx.fill() ctx.fill()
ctx.closePath()
} }
} }
FluArea{ FluArea{

View File

@ -38,6 +38,7 @@ void FluentUIPlugin::registerTypes(const char *uri)
qmlRegisterType<FluColorSet>(uri,major,minor,"FluColorSet"); qmlRegisterType<FluColorSet>(uri,major,minor,"FluColorSet");
qmlRegisterType<FluHttpInterceptor>(uri,major,minor,"FluHttpInterceptor"); qmlRegisterType<FluHttpInterceptor>(uri,major,minor,"FluHttpInterceptor");
qmlRegisterType<FluHttp>(uri,major,minor,"FluHttp"); qmlRegisterType<FluHttp>(uri,major,minor,"FluHttp");
qmlRegisterType<HttpCallable>(uri,major,minor,"HttpCallable");
qmlRegisterUncreatableMetaObject(Fluent_Awesome::staticMetaObject, uri,major,minor,"FluentIcons", "Access to enums & flags only"); qmlRegisterUncreatableMetaObject(Fluent_Awesome::staticMetaObject, uri,major,minor,"FluentIcons", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(FluThemeType::staticMetaObject, uri,major,minor,"FluThemeType", "Access to enums & flags only"); qmlRegisterUncreatableMetaObject(FluThemeType::staticMetaObject, uri,major,minor,"FluThemeType", "Access to enums & flags only");
qmlRegisterUncreatableMetaObject(FluPageType::staticMetaObject, uri,major,minor,"FluPageType", "Access to enums & flags only"); qmlRegisterUncreatableMetaObject(FluPageType::staticMetaObject, uri,major,minor,"FluPageType", "Access to enums & flags only");