Compare commits

...

59 Commits
1.6.3 ... 1.6.5

Author SHA1 Message Date
70e525f51e update 2023-12-20 09:36:19 +08:00
72610da66e update 2023-12-19 20:28:14 +08:00
fde55d254c update 2023-12-19 20:15:48 +08:00
61659b5e31 update 2023-12-19 20:02:15 +08:00
f4112ee5dc update 2023-12-19 18:07:53 +08:00
f973f006d2 update 2023-12-19 18:01:49 +08:00
38ea91964e update 2023-12-19 10:52:39 +08:00
af6e39d8c0 update 2023-12-18 23:56:28 +08:00
6d2a8cde7a update 2023-12-18 22:24:24 +08:00
2bd0a831e7 update 2023-12-18 21:32:56 +08:00
1bf992ed69 fix bug #373 2023-12-18 21:29:38 +08:00
ecd0f29d30 update 2023-12-16 15:25:37 +08:00
5e38493403 update 2023-12-15 22:47:22 +08:00
c5aad9feed update 2023-12-15 22:41:11 +08:00
d347512486 update 2023-12-15 18:17:17 +08:00
136e2c72af update 2023-12-15 16:45:59 +08:00
95f48b51bf update 2023-12-15 16:04:00 +08:00
7ba06d183d update 2023-12-15 11:25:54 +08:00
9ee50a585a update 2023-12-14 23:50:58 +08:00
c95ac86377 update 2023-12-14 22:06:26 +08:00
5787e308dd update 2023-12-14 21:16:09 +08:00
08c458c2a1 update 2023-12-14 14:43:49 +08:00
299eba18ac update 2023-12-14 11:46:51 +08:00
6da8117056 update 2023-12-14 09:41:14 +08:00
e5668869b9 update 2023-12-13 23:43:01 +08:00
65905b139e update 2023-12-13 21:28:21 +08:00
6974b0efa6 update 2023-12-13 18:13:35 +08:00
3c924bb0de update 2023-12-13 17:31:08 +08:00
ec2378a07a update 2023-12-13 16:20:09 +08:00
863c88411b update 2023-12-12 00:49:12 +08:00
6b6dbf27a1 update 2023-12-11 23:47:03 +08:00
dc37a151c8 update 2023-12-11 23:43:17 +08:00
6c86e61916 FluNetwork add Head Request 2023-12-08 23:30:41 +08:00
33c203fcb3 update SettingsHelper 2023-12-08 17:30:50 +08:00
7086df10f0 FluNetwork add openLog funcation 2023-12-07 23:01:09 +08:00
13223a11a2 update 2023-12-07 20:52:17 +08:00
3d65bdc913 update 2023-12-07 18:13:58 +08:00
c80689e376 update 2023-12-07 11:51:59 +08:00
1abbc4593a add log level 2023-12-07 00:20:32 +08:00
c1ffce06aa update log 2023-12-06 23:57:30 +08:00
bd8a561590 update network 2023-12-06 18:23:51 +08:00
eed96b4c0e update 2023-12-05 21:32:23 +08:00
1b4fddec61 update 2023-12-05 18:16:06 +08:00
2c16f6f71a mv framelsshelper and zxing-cpp 2023-12-05 16:45:36 +08:00
3770969097 add chart example 2023-12-05 15:49:02 +08:00
d255f5881e update 2023-12-05 11:42:21 +08:00
711411f6a8 update 2023-12-05 00:20:40 +08:00
f5a4fc1300 fix log bug Chinese garbled character 2023-12-04 23:48:58 +08:00
bc0c36772f update 2023-12-04 21:52:57 +08:00
46148b3c5c update 2023-12-04 21:33:06 +08:00
b4f2f68135 update 2023-12-04 21:25:44 +08:00
5d4cfa5286 fix bug 2023-12-04 21:18:19 +08:00
ee23554cb4 update 2023-12-04 17:55:20 +08:00
a9772a8fb0 update T_Dialog 2023-12-04 17:35:05 +08:00
2428a38194 update FluContentDialog and FluShortcutPicker 2023-12-04 17:10:08 +08:00
1a21cd7b31 update 2023-12-02 23:29:55 +08:00
bcc47c1496 update 2023-12-02 23:04:02 +08:00
95a6be3d28 fix bug #361 2023-12-02 22:48:41 +08:00
9a48880e84 add ShortcutPicker 2023-12-01 18:14:10 +08:00
127 changed files with 35368 additions and 27097 deletions

View File

@ -30,6 +30,7 @@ SolidCompression=yes
WizardStyle=modern WizardStyle=modern
UninstallDisplayIcon={app}\{#MyAppExeName} UninstallDisplayIcon={app}\{#MyAppExeName}
SetupIconFile=.\..\favicon.ico SetupIconFile=.\..\favicon.ico
MinVersion = 6.0
[Languages] [Languages]
Name: "chinesesimplified"; MessagesFile: "compiler:Languages\ChineseSimplified.isl" Name: "chinesesimplified"; MessagesFile: "compiler:Languages\ChineseSimplified.isl"

6
.gitmodules vendored
View File

@ -1,6 +0,0 @@
[submodule "framelesshelper"]
path = framelesshelper
url = https://github.com/zhuzichu520/framelesshelper.git
[submodule "zxing-cpp"]
path = zxing-cpp
url = https://github.com/zhuzichu520/zxing-cpp.git

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
project(FluentUI VERSION 0.1 LANGUAGES CXX) project(FluentUI VERSION 1.0)
set(FLUENTUI_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}) set(FLUENTUI_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
list(APPEND CMAKE_MODULE_PATH ${FLUENTUI_DIRECTORY}/.cmake/) list(APPEND CMAKE_MODULE_PATH ${FLUENTUI_DIRECTORY}/.cmake/)
@ -25,17 +25,16 @@ if(NOT FLUENTUI_QML_PLUGIN_DIRECTORY)
endif() endif()
add_subdirectory(src) add_subdirectory(src)
add_subdirectory(zxing-cpp)
target_compile_definitions(fluentuiplugin
PRIVATE
QT_MESSAGELOGCONTEXT
)
if (FLUENTUI_BUILD_EXAMPLES) if (FLUENTUI_BUILD_EXAMPLES)
add_subdirectory(example) add_subdirectory(example)
endif () endif ()
set(FRAMELESSHELPER_BUILD_STATIC ON)
set(FRAMELESSHELPER_NO_DEBUG_OUTPUT ON)
set(FRAMELESSHELPER_BUILD_WIDGETS OFF)
add_subdirectory(framelesshelper)
message("------------------------ FluentUI ------------------------") message("------------------------ FluentUI ------------------------")
message("Build FluentUI demo applications.: ${FLUENTUI_BUILD_EXAMPLES}") message("Build FluentUI demo applications.: ${FLUENTUI_BUILD_EXAMPLES}")
message("Build static library.: ${FLUENTUI_BUILD_STATIC_LIB}") message("Build static library.: ${FLUENTUI_BUILD_STATIC_LIB}")

View File

@ -1,12 +1,10 @@
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
project(example VERSION 0.1 LANGUAGES CXX) project(example VERSION 1.0)
#配置通用编译 #配置通用编译
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(APPLE)
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
endif()
#导入exmaple的QML位置不然import example有时候会爆红 #导入exmaple的QML位置不然import example有时候会爆红
set(QML_IMPORT_PATH ${CMAKE_BINARY_DIR}/example CACHE STRING "Qt Creator extra QML import paths" FORCE) set(QML_IMPORT_PATH ${CMAKE_BINARY_DIR}/example CACHE STRING "Qt Creator extra QML import paths" FORCE)
@ -155,6 +153,11 @@ set_target_properties(example PROPERTIES
WIN32_EXECUTABLE TRUE WIN32_EXECUTABLE TRUE
) )
target_compile_definitions(example
PRIVATE
QT_MESSAGELOGCONTEXT
)
target_link_libraries(example PRIVATE target_link_libraries(example PRIVATE
Qt${QT_VERSION_MAJOR}::Quick Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::Svg Qt${QT_VERSION_MAJOR}::Svg

View File

@ -134,7 +134,6 @@
<file>qml/page/T_CalendarPicker.qml</file> <file>qml/page/T_CalendarPicker.qml</file>
<file>qml/page/T_Captcha.qml</file> <file>qml/page/T_Captcha.qml</file>
<file>qml/page/T_Carousel.qml</file> <file>qml/page/T_Carousel.qml</file>
<file>qml/page/T_Chart.qml</file>
<file>qml/page/T_CheckBox.qml</file> <file>qml/page/T_CheckBox.qml</file>
<file>qml/page/T_ColorPicker.qml</file> <file>qml/page/T_ColorPicker.qml</file>
<file>qml/page/T_ComboBox.qml</file> <file>qml/page/T_ComboBox.qml</file>
@ -189,5 +188,13 @@
<file>qml/page/T_3D.qml</file> <file>qml/page/T_3D.qml</file>
<file>qml/global/Lang.qml</file> <file>qml/global/Lang.qml</file>
<file>qml/page/T_Network.qml</file> <file>qml/page/T_Network.qml</file>
<file>qml/page/T_ShortcutPicker.qml</file>
<file>qml/chart/T_BarChart.qml</file>
<file>qml/chart/T_LineChart.qml</file>
<file>qml/chart/T_PieChart.qml</file>
<file>qml/chart/T_RadarChart.qml</file>
<file>qml/chart/T_ScatterChart.qml</file>
<file>qml/chart/T_BubbleChart.qml</file>
<file>qml/chart/T_PolarAreaChart.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -16,21 +16,19 @@ Item {
Connections{ Connections{
target: FluApp target: FluApp
function onVsyncChanged(){
SettingsHelper.saveVsync(FluApp.vsync)
}
function onUseSystemAppBarChanged(){ function onUseSystemAppBarChanged(){
SettingsHelper.saveUseSystemAppBar(FluApp.useSystemAppBar) SettingsHelper.saveUseSystemAppBar(FluApp.useSystemAppBar)
} }
} }
Component.onCompleted: { Component.onCompleted: {
FluNetwork.openLog = false
FluNetwork.setInterceptor(function(param){ FluNetwork.setInterceptor(function(param){
param.addHeader("Token","000000000000000000000") param.addHeader("Token","000000000000000000000")
}) })
FluApp.init(app) FluApp.init(app)
FluApp.windowIcon = "qrc:/example/res/image/favicon.ico"
FluApp.useSystemAppBar = SettingsHelper.getUseSystemAppBar() FluApp.useSystemAppBar = SettingsHelper.getUseSystemAppBar()
FluApp.vsync = SettingsHelper.getVsync()
FluTheme.darkMode = SettingsHelper.getDarkMode() FluTheme.darkMode = SettingsHelper.getDarkMode()
FluTheme.enableAnimation = true FluTheme.enableAnimation = true
FluApp.routes = { FluApp.routes = {

View File

@ -0,0 +1,132 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Bar Chart"
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'bar'
chartData: { return {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'My First Dataset',
data: [65, 59, 80, 81, 56, 55, 40],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(255, 205, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(201, 203, 207, 0.2)'
],
borderColor: [
'rgb(255, 99, 132)',
'rgb(255, 159, 64)',
'rgb(255, 205, 86)',
'rgb(75, 192, 192)',
'rgb(54, 162, 235)',
'rgb(153, 102, 255)',
'rgb(201, 203, 207)'
],
borderWidth: 1
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js Bar Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
}
}
}
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'horizontalBar'
chartData: { return {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'My First Dataset',
data: [65, 59, 80, 81, 56, 55, 40],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(255, 205, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(201, 203, 207, 0.2)'
],
borderColor: [
'rgb(255, 99, 132)',
'rgb(255, 159, 64)',
'rgb(255, 205, 86)',
'rgb(75, 192, 192)',
'rgb(54, 162, 235)',
'rgb(153, 102, 255)',
'rgb(201, 203, 207)'
],
borderWidth: 1
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js HorizontalBar Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
}
}
}
}

View File

@ -0,0 +1,74 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Bubble Chart"
function randomScalingFactor() {
return Math.random().toFixed(1);
}
FluArea{
height: 370
width: 500
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'bubble'
chartData: {
return {
datasets: [{
label: 'First Dataset',
data: [{
x: 20,
y: 30,
r: 15
}, {
x: 12,
y: 70,
r: 20
}, {
x: 11,
y: 28,
r: 8
}, {
x: 9,
y: 28,
r: 10
}, {
x: 43,
y: 7,
r: 14
}, {
x: 22,
y: 22,
r: 12
}, {
x: 40,
y: 10,
r: 10
}],
backgroundColor: 'rgb(255, 99, 132)'
}]
}}
chartOptions: {return {
maintainAspectRatio: false,
responsive: true,
hoverMode: 'nearest',
intersect: true,
title: {
display: true,
text: 'Chart.js Bubble Chart - Multi Axis'
}
}
}
}
}
}

View File

@ -0,0 +1,45 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Line Chart"
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'line'
chartData: { return {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'My First Dataset',
data: [65, 59, 80, 81, 56, 55, 40],
fill: false,
borderColor: 'rgb(75, 192, 192)',
tension: 0.1
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js Line Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
}
}
}
}
}
}

View File

@ -0,0 +1,93 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Doughnut and Pie Chart"
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: "doughnut"
chartData: { return {
labels: [
'Red',
'Blue',
'Yellow'
],
datasets: [{
label: 'My First Dataset',
data: [300, 50, 100],
backgroundColor: [
'rgb(255, 99, 132)',
'rgb(54, 162, 235)',
'rgb(255, 205, 86)'
],
hoverOffset: 4
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js Doughnut Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
}
}
}
}
}
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: "pie"
chartData: { return {
labels: [
'Red',
'Blue',
'Yellow'
],
datasets: [{
label: 'My First Dataset',
data: [300, 50, 100],
backgroundColor: [
'rgb(255, 99, 132)',
'rgb(54, 162, 235)',
'rgb(255, 205, 86)'
],
hoverOffset: 4
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js Pie Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
}
}
}
}
}
}

View File

@ -0,0 +1,57 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage{
title:"PolarArea Chart"
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'polarArea'
chartData: { return {
labels: [
'Red',
'Green',
'Yellow',
'Grey',
'Blue'
],
datasets: [{
label: 'My First Dataset',
data: [11, 16, 7, 3, 14],
backgroundColor: [
'rgb(255, 99, 132)',
'rgb(75, 192, 192)',
'rgb(255, 205, 86)',
'rgb(201, 203, 207)',
'rgb(54, 162, 235)'
]
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js PolarArea Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
}
}
}
}
}
}

View File

@ -0,0 +1,74 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Radar Chart"
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'radar'
chartData: { return {
labels: [
'Eating',
'Drinking',
'Sleeping',
'Designing',
'Coding',
'Cycling',
'Running'
],
datasets:
[{
label: 'My First Dataset',
data: [65, 59, 90, 81, 56, 55, 40],
fill: true,
backgroundColor: 'rgba(255, 99, 132, 0.2)',
borderColor: 'rgb(255, 99, 132)',
pointBackgroundColor: 'rgb(255, 99, 132)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgb(255, 99, 132)'
}, {
label: 'My Second Dataset',
data: [28, 48, 40, 19, 96, 27, 100],
fill: true,
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgb(54, 162, 235)',
pointBackgroundColor: 'rgb(54, 162, 235)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgb(54, 162, 235)'
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js Radar Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
},
elements: {
line: {
borderWidth: 3
}
}
}
}
}
}
}

View File

@ -0,0 +1,123 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Scatter Chart"
function randomScalingFactor() {
return Math.random().toFixed(1);
}
FluArea{
height: 370
width: 500
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'scatter'
chartData: {
return {
datasets: [{
label: 'My First dataset',
xAxisID: 'x-axis-1',
yAxisID: 'y-axis-1',
borderColor: '#ff5555',
backgroundColor: 'rgba(255,192,192,0.3)',
data: [{
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}]
}, {
label: 'My Second dataset',
xAxisID: 'x-axis-1',
yAxisID: 'y-axis-2',
borderColor: '#5555ff',
backgroundColor: 'rgba(192,192,255,0.3)',
data: [{
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}]
}]
}}
chartOptions: {return {
maintainAspectRatio: false,
responsive: true,
hoverMode: 'nearest',
intersect: true,
title: {
display: true,
text: 'Chart.js Scatter Chart - Multi Axis'
},
scales: {
xAxes: [{
position: 'bottom',
gridLines: {
zeroLineColor: 'rgba(0,0,0,1)'
}
}],
yAxes: [{
type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: 'left',
id: 'y-axis-1',
}, {
type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: 'right',
reverse: true,
id: 'y-axis-2',
// grid line settings
gridLines: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
}],
}
}
}
}
}
}

View File

@ -140,7 +140,8 @@ FluExpander{
"FluProgressButton", "FluProgressButton",
"FluLoadingButton", "FluLoadingButton",
"FluClip", "FluClip",
"FluNetwork" "FluNetwork",
"FluShortcutPicker"
]; ];
code = code.replace(/\n/g, "<br>"); code = code.replace(/\n/g, "<br>");
code = code.replace(/ /g, "&nbsp;"); code = code.replace(/ /g, "&nbsp;");

View File

@ -150,6 +150,12 @@ FluObject{
url:"qrc:/example/qml/page/T_ColorPicker.qml" url:"qrc:/example/qml/page/T_ColorPicker.qml"
onTap:{ navigationView.push(url) } onTap:{ navigationView.push(url) }
} }
FluPaneItem{
title:"ShortcutPicker"
menuDelegate: paneItemMenu
url:"qrc:/example/qml/page/T_ShortcutPicker.qml"
onTap:{ navigationView.push(url) }
}
} }
FluPaneItemExpander{ FluPaneItemExpander{
@ -362,6 +368,53 @@ FluObject{
} }
} }
FluPaneItemExpander{
title: Lang.chart
icon:FluentIcons.AreaChart
FluPaneItem{
title:Lang.bar_chart
menuDelegate: paneItemMenu
url:"qrc:/example/qml/chart/T_BarChart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:Lang.line_chart
menuDelegate: paneItemMenu
url:"qrc:/example/qml/chart/T_LineChart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:Lang.pie_chart
menuDelegate: paneItemMenu
url:"qrc:/example/qml/chart/T_PieChart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:Lang.polar_area_chart
menuDelegate: paneItemMenu
url:"qrc:/example/qml/chart/T_PolarAreaChart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:Lang.bubble_chart
menuDelegate: paneItemMenu
url:"qrc:/example/qml/chart/T_BubbleChart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:Lang.scatter_chart
menuDelegate: paneItemMenu
url:"qrc:/example/qml/chart/T_ScatterChart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:Lang.radar_chart
menuDelegate: paneItemMenu
url:"qrc:/example/qml/chart/T_RadarChart.qml"
onTap:{ navigationView.push(url) }
}
}
FluPaneItemSeparator{ FluPaneItemSeparator{
spacing:10 spacing:10
size:1 size:1
@ -400,12 +453,6 @@ FluObject{
url:"qrc:/example/qml/page/T_Captcha.qml" url:"qrc:/example/qml/page/T_Captcha.qml"
onTap:{ navigationView.push(url) } onTap:{ navigationView.push(url) }
} }
FluPaneItem{
title:"Chart"
menuDelegate: paneItemMenu
url:"qrc:/example/qml/page/T_Chart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{ FluPaneItem{
title:"Network" title:"Network"
menuDelegate: paneItemMenu menuDelegate: paneItemMenu

View File

@ -20,6 +20,14 @@ QtObject {
property string locale property string locale
property string navigation_view_display_mode property string navigation_view_display_mode
property string other property string other
property string chart
property string bar_chart
property string line_chart
property string pie_chart
property string polar_area_chart
property string bubble_chart
property string scatter_chart
property string radar_chart
function zh(){ function zh(){
home="首页" home="首页"
@ -38,6 +46,14 @@ QtObject {
locale="语言环境" locale="语言环境"
navigation_view_display_mode="导航视图显示模式" navigation_view_display_mode="导航视图显示模式"
other="其他" other="其他"
chart="表格"
bar_chart="条形图"
line_chart="折线图"
pie_chart="饼图"
polar_area_chart="极坐标区域图"
bubble_chart="气泡图"
scatter_chart="散点图"
radar_chart="雷达图"
} }
function en(){ function en(){
@ -57,6 +73,14 @@ QtObject {
locale="Locale" locale="Locale"
navigation_view_display_mode="NavigationView Display Mode" navigation_view_display_mode="NavigationView Display Mode"
other="Other" other="Other"
chart="Chart"
bar_chart="Bar Chart"
line_chart="Line Chart"
pie_chart="Pie Chart"
polar_area_chart="Polar Area Chart"
bubble_chart="Bubble Chart"
scatter_chart="Scatter Chart"
radar_chart="Radar Chart"
} }
property string __locale property string __locale

View File

@ -1,331 +0,0 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage{
title:"Chart"
function randomScalingFactor() {
return Math.random().toFixed(1);
}
FluArea{
height: 370
width: 500
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'scatter'
chartData: {
return {
datasets: [{
label: 'My First dataset',
xAxisID: 'x-axis-1',
yAxisID: 'y-axis-1',
borderColor: '#ff5555',
backgroundColor: 'rgba(255,192,192,0.3)',
data: [{
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}]
}, {
label: 'My Second dataset',
xAxisID: 'x-axis-1',
yAxisID: 'y-axis-2',
borderColor: '#5555ff',
backgroundColor: 'rgba(192,192,255,0.3)',
data: [{
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}]
}]
}}
chartOptions: {return {
maintainAspectRatio: false,
responsive: true,
hoverMode: 'nearest',
intersect: true,
title: {
display: true,
text: 'Chart.js Scatter Chart - Multi Axis'
},
scales: {
xAxes: [{
position: 'bottom',
gridLines: {
zeroLineColor: 'rgba(0,0,0,1)'
}
}],
yAxes: [{
type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: 'left',
id: 'y-axis-1',
}, {
type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: 'right',
reverse: true,
id: 'y-axis-2',
// grid line settings
gridLines: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
}],
}
}
}
}
}
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'bar'
chartData: { return {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'Dataset 1',
backgroundColor: '#ff9999',
stack: 'Stack 0',
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
]
}, {
label: 'Dataset 2',
backgroundColor: '#9999ff',
stack: 'Stack 0',
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
]
}, {
label: 'Dataset 3',
backgroundColor: '#99ff99',
stack: 'Stack 1',
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
]
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js Bar Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
}
}
}
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'pie'
chartData: {return {
datasets: [{
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
],
backgroundColor: [
'#ffbbbb',
'#ffddaa',
'#ffffbb',
'#bbffbb',
'#bbbbff'
],
label: 'Dataset 1'
}],
labels: [
'Red',
'Orange',
'Yellow',
'Green',
'Blue'
]
}}
chartOptions: {return {maintainAspectRatio: false, responsive: true}}
}
}
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'line'
chartData: { return {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'Filled',
fill: true,
backgroundColor: 'rgba(192,222,255,0.3)',
borderColor: 'rgba(128,192,255,255)',
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
],
}, {
label: 'Dashed',
fill: false,
backgroundColor: 'rgba(0,0,0,0)',
borderColor: '#009900',
borderDash: [5, 5],
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
],
}, {
label: 'Filled',
backgroundColor: 'rgba(0,0,0,0)',
borderColor: '#990000',
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
],
fill: false,
}]
}
}
chartOptions: {return {
maintainAspectRatio: false,
responsive: true,
title: {
display: true,
text: 'Chart.js Line Chart'
},
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Month'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Value'
}
}]
}
}
}
}
}
}

View File

@ -115,4 +115,68 @@ FluScrollablePage{
showSuccess("点击最小化按钮") showSuccess("点击最小化按钮")
} }
} }
FluArea{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20
FluButton{
anchors.verticalCenter: parent.verticalCenter
Layout.topMargin: 20
text:"Custom Content Dialog"
onClicked: {
custom_btn_dialog.open()
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluContentDialog{
id:dialog
title:"友情提示"
message:"数据正在加载中,请稍等..."
negativeText:"取消加载"
contentDelegate: Component{
Item{
width: parent.width
height: 80
FluProgressRing{
anchors.centerIn: parent
}
}
}
onNegativeClicked:{
showSuccess("点击取消按钮")
}
positiveText:"确定"
onPositiveClicked:{
showSuccess("点击确定按钮")
}
dialog.open()'
}
FluContentDialog{
id:custom_btn_dialog
title:"友情提示"
message:"数据正在加载中,请稍等..."
negativeText:"取消加载"
contentDelegate: Component{
Item{
width: parent.width
height: 80
FluProgressRing{
anchors.centerIn: parent
}
}
}
onNegativeClicked:{
showSuccess("点击取消按钮")
}
positiveText:"确定"
onPositiveClicked:{
showSuccess("点击确定按钮")
}
}
} }

View File

@ -64,6 +64,20 @@ FluContentPage{
.go(callable) .go(callable)
} }
} }
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Head"
onClicked: {
text_info.text = ""
FluNetwork.head("https://httpbingo.org/head")
.addQuery("name","孙悟空")
.addQuery("age",500)
.addQuery("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
FluButton{ FluButton{
implicitWidth: parent.width implicitWidth: parent.width
implicitHeight: 36 implicitHeight: 36
@ -280,6 +294,21 @@ FluContentPage{
.go(callable) .go(callable)
} }
} }
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Open Log"
onClicked: {
text_info.text = ""
FluNetwork.postJson("https://httpbingo.org/post")
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.openLog(true)
.bind(root)
.go(callable)
}
}
FluButton{ FluButton{
implicitWidth: parent.width implicitWidth: parent.width
implicitHeight: 36 implicitHeight: 36

View File

@ -56,22 +56,6 @@ FluScrollablePage{
} }
} }
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 50
paddings: 10
FluCheckBox{
text:"V-Sync"
checked: FluApp.vsync
anchors.verticalCenter: parent.verticalCenter
onClicked: {
FluApp.vsync = !FluApp.vsync
dialog_restart.open()
}
}
}
FluArea{ FluArea{
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20

View File

@ -0,0 +1,30 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Window
import FluentUI
import "qrc:///example/qml/component"
FluScrollablePage{
title:"ShortcutPicker"
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 100
paddings: 10
FluShortcutPicker{
anchors.verticalCenter: parent.verticalCenter
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluShortcutPicker{
}'
}
}

View File

@ -13,14 +13,13 @@ FluWindow {
id:window id:window
title: "FluentUI" title: "FluentUI"
width: 1000 width: 960
height: 640 height: 600
minimumWidth: 520 minimumWidth: 520
minimumHeight: 200 minimumHeight: 200
launchMode: FluWindowType.SingleTask launchMode: FluWindowType.SingleTask
fitsAppBarWindows: true fitsAppBarWindows: true
appBar: FluAppBar { appBar: FluAppBar {
width: window.width
height: 30 height: 30
darkText: Lang.dark_mode darkText: Lang.dark_mode
showDark: true showDark: true
@ -42,8 +41,16 @@ FluWindow {
} }
onFirstVisible: { onFirstVisible: {
timer_tour_delay.restart()
}
Timer{
id:timer_tour_delay
interval: 200
onTriggered: {
tour.open() tour.open()
} }
}
Component.onCompleted: { Component.onCompleted: {
checkUpdate(true) checkUpdate(true)
@ -77,6 +84,14 @@ FluWindow {
} }
} }
Timer{
id:timer_window_hide_delay
interval: 150
onTriggered: {
window.hide()
}
}
FluContentDialog{ FluContentDialog{
id:dialog_close id:dialog_close
title:"退出" title:"退出"
@ -84,8 +99,8 @@ FluWindow {
negativeText:"最小化" negativeText:"最小化"
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.NeutralButton | FluContentDialogType.PositiveButton buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.NeutralButton | FluContentDialogType.PositiveButton
onNegativeClicked: { onNegativeClicked: {
window.hide()
system_tray.showMessage("友情提示","FluentUI已隐藏至托盘,点击托盘可再次激活窗口"); system_tray.showMessage("友情提示","FluentUI已隐藏至托盘,点击托盘可再次激活窗口");
timer_window_hide_delay.restart()
} }
positiveText:"退出" positiveText:"退出"
neutralText:"取消" neutralText:"取消"
@ -183,7 +198,12 @@ FluWindow {
pageMode: FluNavigationViewType.NoStack pageMode: FluNavigationViewType.NoStack
items: ItemsOriginal items: ItemsOriginal
footerItems:ItemsFooter footerItems:ItemsFooter
topPadding:FluTools.isMacos() ? 20 : 0 topPadding:{
if(window.useSystemAppBar){
return 0
}
return FluTools.isMacos() ? 20 : 0
}
displayMode:viewmodel_settings.displayMode displayMode:viewmodel_settings.displayMode
logo: "qrc:/example/res/image/favicon.ico" logo: "qrc:/example/res/image/favicon.ico"
title:"FluentUI" title:"FluentUI"
@ -220,7 +240,7 @@ FluWindow {
id:com_reveal id:com_reveal
CircularReveal{ CircularReveal{
id:reveal id:reveal
target:window.contentItem target:window.layoutContainer()
anchors.fill: parent anchors.fill: parent
onAnimationFinished:{ onAnimationFinished:{
//动画结束后释放资源 //动画结束后释放资源
@ -245,8 +265,11 @@ FluWindow {
if(!FluTheme.enableAnimation || window.fitsAppBarWindows === false){ if(!FluTheme.enableAnimation || window.fitsAppBarWindows === false){
changeDark() changeDark()
}else{ }else{
if(loader_reveal.sourceComponent){
return
}
loader_reveal.sourceComponent = com_reveal loader_reveal.sourceComponent = com_reveal
var target = window.contentItem var target = window.layoutContainer()
var pos = button.mapToItem(target,0,0) var pos = button.mapToItem(target,0,0)
var mouseX = pos.x var mouseX = pos.x
var mouseY = pos.y var mouseY = pos.y

View File

@ -16,21 +16,19 @@ Item {
Connections{ Connections{
target: FluApp target: FluApp
function onVsyncChanged(){
SettingsHelper.saveVsync(FluApp.vsync)
}
function onUseSystemAppBarChanged(){ function onUseSystemAppBarChanged(){
SettingsHelper.saveUseSystemAppBar(FluApp.useSystemAppBar) SettingsHelper.saveUseSystemAppBar(FluApp.useSystemAppBar)
} }
} }
Component.onCompleted: { Component.onCompleted: {
FluNetwork.openLog = false
FluNetwork.setInterceptor(function(param){ FluNetwork.setInterceptor(function(param){
param.addHeader("Token","000000000000000000000") param.addHeader("Token","000000000000000000000")
}) })
FluApp.init(app) FluApp.init(app)
FluApp.windowIcon = "qrc:/example/res/image/favicon.ico"
FluApp.useSystemAppBar = SettingsHelper.getUseSystemAppBar() FluApp.useSystemAppBar = SettingsHelper.getUseSystemAppBar()
FluApp.vsync = SettingsHelper.getVsync()
FluTheme.darkMode = SettingsHelper.getDarkMode() FluTheme.darkMode = SettingsHelper.getDarkMode()
FluTheme.enableAnimation = true FluTheme.enableAnimation = true
FluApp.routes = { FluApp.routes = {

View File

@ -0,0 +1,133 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
FluScrollablePage{
title:"Bar Chart"
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'bar'
chartData: { return {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'My First Dataset',
data: [65, 59, 80, 81, 56, 55, 40],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(255, 205, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(201, 203, 207, 0.2)'
],
borderColor: [
'rgb(255, 99, 132)',
'rgb(255, 159, 64)',
'rgb(255, 205, 86)',
'rgb(75, 192, 192)',
'rgb(54, 162, 235)',
'rgb(153, 102, 255)',
'rgb(201, 203, 207)'
],
borderWidth: 1
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js Bar Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
}
}
}
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'horizontalBar'
chartData: { return {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'My First Dataset',
data: [65, 59, 80, 81, 56, 55, 40],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(255, 205, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(201, 203, 207, 0.2)'
],
borderColor: [
'rgb(255, 99, 132)',
'rgb(255, 159, 64)',
'rgb(255, 205, 86)',
'rgb(75, 192, 192)',
'rgb(54, 162, 235)',
'rgb(153, 102, 255)',
'rgb(201, 203, 207)'
],
borderWidth: 1
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js HorizontalBar Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
}
}
}
}

View File

@ -0,0 +1,75 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
FluScrollablePage{
title:"Bubble Chart"
function randomScalingFactor() {
return Math.random().toFixed(1);
}
FluArea{
height: 370
width: 500
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'bubble'
chartData: {
return {
datasets: [{
label: 'First Dataset',
data: [{
x: 20,
y: 30,
r: 15
}, {
x: 12,
y: 70,
r: 20
}, {
x: 11,
y: 28,
r: 8
}, {
x: 9,
y: 28,
r: 10
}, {
x: 43,
y: 7,
r: 14
}, {
x: 22,
y: 22,
r: 12
}, {
x: 40,
y: 10,
r: 10
}],
backgroundColor: 'rgb(255, 99, 132)'
}]
}}
chartOptions: {return {
maintainAspectRatio: false,
responsive: true,
hoverMode: 'nearest',
intersect: true,
title: {
display: true,
text: 'Chart.js Bubble Chart - Multi Axis'
}
}
}
}
}
}

View File

@ -0,0 +1,46 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
FluScrollablePage{
title:"Line Chart"
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'line'
chartData: { return {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'My First Dataset',
data: [65, 59, 80, 81, 56, 55, 40],
fill: false,
borderColor: 'rgb(75, 192, 192)',
tension: 0.1
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js Line Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
}
}
}
}
}
}

View File

@ -0,0 +1,94 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
FluScrollablePage{
title:"Doughnut and Pie Chart"
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: "doughnut"
chartData: { return {
labels: [
'Red',
'Blue',
'Yellow'
],
datasets: [{
label: 'My First Dataset',
data: [300, 50, 100],
backgroundColor: [
'rgb(255, 99, 132)',
'rgb(54, 162, 235)',
'rgb(255, 205, 86)'
],
hoverOffset: 4
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js Doughnut Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
}
}
}
}
}
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: "pie"
chartData: { return {
labels: [
'Red',
'Blue',
'Yellow'
],
datasets: [{
label: 'My First Dataset',
data: [300, 50, 100],
backgroundColor: [
'rgb(255, 99, 132)',
'rgb(54, 162, 235)',
'rgb(255, 205, 86)'
],
hoverOffset: 4
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js Pie Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
}
}
}
}
}
}

View File

@ -0,0 +1,58 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
FluScrollablePage{
title:"PolarArea Chart"
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'polarArea'
chartData: { return {
labels: [
'Red',
'Green',
'Yellow',
'Grey',
'Blue'
],
datasets: [{
label: 'My First Dataset',
data: [11, 16, 7, 3, 14],
backgroundColor: [
'rgb(255, 99, 132)',
'rgb(75, 192, 192)',
'rgb(255, 205, 86)',
'rgb(201, 203, 207)',
'rgb(54, 162, 235)'
]
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js PolarArea Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
}
}
}
}
}
}

View File

@ -0,0 +1,75 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
FluScrollablePage{
title:"Radar Chart"
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'radar'
chartData: { return {
labels: [
'Eating',
'Drinking',
'Sleeping',
'Designing',
'Coding',
'Cycling',
'Running'
],
datasets:
[{
label: 'My First Dataset',
data: [65, 59, 90, 81, 56, 55, 40],
fill: true,
backgroundColor: 'rgba(255, 99, 132, 0.2)',
borderColor: 'rgb(255, 99, 132)',
pointBackgroundColor: 'rgb(255, 99, 132)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgb(255, 99, 132)'
}, {
label: 'My Second Dataset',
data: [28, 48, 40, 19, 96, 27, 100],
fill: true,
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgb(54, 162, 235)',
pointBackgroundColor: 'rgb(54, 162, 235)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgb(54, 162, 235)'
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js Radar Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
},
elements: {
line: {
borderWidth: 3
}
}
}
}
}
}
}

View File

@ -0,0 +1,124 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
FluScrollablePage{
title:"Scatter Chart"
function randomScalingFactor() {
return Math.random().toFixed(1);
}
FluArea{
height: 370
width: 500
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'scatter'
chartData: {
return {
datasets: [{
label: 'My First dataset',
xAxisID: 'x-axis-1',
yAxisID: 'y-axis-1',
borderColor: '#ff5555',
backgroundColor: 'rgba(255,192,192,0.3)',
data: [{
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}]
}, {
label: 'My Second dataset',
xAxisID: 'x-axis-1',
yAxisID: 'y-axis-2',
borderColor: '#5555ff',
backgroundColor: 'rgba(192,192,255,0.3)',
data: [{
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}]
}]
}}
chartOptions: {return {
maintainAspectRatio: false,
responsive: true,
hoverMode: 'nearest',
intersect: true,
title: {
display: true,
text: 'Chart.js Scatter Chart - Multi Axis'
},
scales: {
xAxes: [{
position: 'bottom',
gridLines: {
zeroLineColor: 'rgba(0,0,0,1)'
}
}],
yAxes: [{
type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: 'left',
id: 'y-axis-1',
}, {
type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: 'right',
reverse: true,
id: 'y-axis-2',
// grid line settings
gridLines: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
}],
}
}
}
}
}
}

View File

@ -140,7 +140,8 @@ FluExpander{
"FluProgressButton", "FluProgressButton",
"FluLoadingButton", "FluLoadingButton",
"FluClip", "FluClip",
"FluNetwork" "FluNetwork",
"FluShortcutPicker"
]; ];
code = code.replace(/\n/g, "<br>"); code = code.replace(/\n/g, "<br>");
code = code.replace(/ /g, "&nbsp;"); code = code.replace(/ /g, "&nbsp;");

View File

@ -150,6 +150,12 @@ FluObject{
url:"qrc:/example/qml/page/T_ColorPicker.qml" url:"qrc:/example/qml/page/T_ColorPicker.qml"
onTap:{ navigationView.push(url) } onTap:{ navigationView.push(url) }
} }
FluPaneItem{
title:"ShortcutPicker"
menuDelegate: paneItemMenu
url:"qrc:/example/qml/page/T_ShortcutPicker.qml"
onTap:{ navigationView.push(url) }
}
} }
FluPaneItemExpander{ FluPaneItemExpander{
@ -362,6 +368,53 @@ FluObject{
} }
} }
FluPaneItemExpander{
title: Lang.chart
icon:FluentIcons.AreaChart
FluPaneItem{
title:Lang.bar_chart
menuDelegate: paneItemMenu
url:"qrc:/example/qml/chart/T_BarChart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:Lang.line_chart
menuDelegate: paneItemMenu
url:"qrc:/example/qml/chart/T_LineChart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:Lang.pie_chart
menuDelegate: paneItemMenu
url:"qrc:/example/qml/chart/T_PieChart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:Lang.polar_area_chart
menuDelegate: paneItemMenu
url:"qrc:/example/qml/chart/T_PolarAreaChart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:Lang.bubble_chart
menuDelegate: paneItemMenu
url:"qrc:/example/qml/chart/T_BubbleChart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:Lang.scatter_chart
menuDelegate: paneItemMenu
url:"qrc:/example/qml/chart/T_ScatterChart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{
title:Lang.radar_chart
menuDelegate: paneItemMenu
url:"qrc:/example/qml/chart/T_RadarChart.qml"
onTap:{ navigationView.push(url) }
}
}
FluPaneItemSeparator{ FluPaneItemSeparator{
spacing:10 spacing:10
size:1 size:1
@ -400,12 +453,6 @@ FluObject{
url:"qrc:/example/qml/page/T_Captcha.qml" url:"qrc:/example/qml/page/T_Captcha.qml"
onTap:{ navigationView.push(url) } onTap:{ navigationView.push(url) }
} }
FluPaneItem{
title:"Chart"
menuDelegate: paneItemMenu
url:"qrc:/example/qml/page/T_Chart.qml"
onTap:{ navigationView.push(url) }
}
FluPaneItem{ FluPaneItem{
title:"Network" title:"Network"
menuDelegate: paneItemMenu menuDelegate: paneItemMenu

View File

@ -20,6 +20,14 @@ QtObject {
property string locale property string locale
property string navigation_view_display_mode property string navigation_view_display_mode
property string other property string other
property string chart
property string bar_chart
property string line_chart
property string pie_chart
property string polar_area_chart
property string bubble_chart
property string scatter_chart
property string radar_chart
function zh(){ function zh(){
home="首页" home="首页"
@ -38,6 +46,14 @@ QtObject {
locale="语言环境" locale="语言环境"
navigation_view_display_mode="导航视图显示模式" navigation_view_display_mode="导航视图显示模式"
other="其他" other="其他"
chart="表格"
bar_chart="条形图"
line_chart="折线图"
pie_chart="饼图"
polar_area_chart="极坐标区域图"
bubble_chart="气泡图"
scatter_chart="散点图"
radar_chart="雷达图"
} }
function en(){ function en(){
@ -57,6 +73,14 @@ QtObject {
locale="Locale" locale="Locale"
navigation_view_display_mode="NavigationView Display Mode" navigation_view_display_mode="NavigationView Display Mode"
other="Other" other="Other"
chart="Chart"
bar_chart="Bar Chart"
line_chart="Line Chart"
pie_chart="Pie Chart"
polar_area_chart="Polar Area Chart"
bubble_chart="Bubble Chart"
scatter_chart="Scatter Chart"
radar_chart="Radar Chart"
} }
property string __locale property string __locale

View File

@ -1,332 +0,0 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
import "qrc:///example/qml/component"
import "../component"
FluScrollablePage{
title:"Chart"
function randomScalingFactor() {
return Math.random().toFixed(1);
}
FluArea{
height: 370
width: 500
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'scatter'
chartData: {
return {
datasets: [{
label: 'My First dataset',
xAxisID: 'x-axis-1',
yAxisID: 'y-axis-1',
borderColor: '#ff5555',
backgroundColor: 'rgba(255,192,192,0.3)',
data: [{
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}]
}, {
label: 'My Second dataset',
xAxisID: 'x-axis-1',
yAxisID: 'y-axis-2',
borderColor: '#5555ff',
backgroundColor: 'rgba(192,192,255,0.3)',
data: [{
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}, {
x: randomScalingFactor(),
y: randomScalingFactor(),
}]
}]
}}
chartOptions: {return {
maintainAspectRatio: false,
responsive: true,
hoverMode: 'nearest',
intersect: true,
title: {
display: true,
text: 'Chart.js Scatter Chart - Multi Axis'
},
scales: {
xAxes: [{
position: 'bottom',
gridLines: {
zeroLineColor: 'rgba(0,0,0,1)'
}
}],
yAxes: [{
type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: 'left',
id: 'y-axis-1',
}, {
type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: 'right',
reverse: true,
id: 'y-axis-2',
// grid line settings
gridLines: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
}],
}
}
}
}
}
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'bar'
chartData: { return {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'Dataset 1',
backgroundColor: '#ff9999',
stack: 'Stack 0',
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
]
}, {
label: 'Dataset 2',
backgroundColor: '#9999ff',
stack: 'Stack 0',
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
]
}, {
label: 'Dataset 3',
backgroundColor: '#99ff99',
stack: 'Stack 1',
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
]
}]
}
}
chartOptions: { return {
maintainAspectRatio: false,
title: {
display: true,
text: 'Chart.js Bar Chart - Stacked'
},
tooltips: {
mode: 'index',
intersect: false
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
}
}
}
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'pie'
chartData: {return {
datasets: [{
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
],
backgroundColor: [
'#ffbbbb',
'#ffddaa',
'#ffffbb',
'#bbffbb',
'#bbbbff'
],
label: 'Dataset 1'
}],
labels: [
'Red',
'Orange',
'Yellow',
'Green',
'Blue'
]
}}
chartOptions: {return {maintainAspectRatio: false, responsive: true}}
}
}
FluArea{
width: 500
height: 370
paddings: 10
Layout.topMargin: 20
FluChart{
anchors.fill: parent
chartType: 'line'
chartData: { return {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'Filled',
fill: true,
backgroundColor: 'rgba(192,222,255,0.3)',
borderColor: 'rgba(128,192,255,255)',
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
],
}, {
label: 'Dashed',
fill: false,
backgroundColor: 'rgba(0,0,0,0)',
borderColor: '#009900',
borderDash: [5, 5],
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
],
}, {
label: 'Filled',
backgroundColor: 'rgba(0,0,0,0)',
borderColor: '#990000',
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
],
fill: false,
}]
}
}
chartOptions: {return {
maintainAspectRatio: false,
responsive: true,
title: {
display: true,
text: 'Chart.js Line Chart'
},
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Month'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Value'
}
}]
}
}
}
}
}
}

View File

@ -116,4 +116,68 @@ FluScrollablePage{
showSuccess("点击最小化按钮") showSuccess("点击最小化按钮")
} }
} }
FluArea{
Layout.fillWidth: true
height: 68
paddings: 10
Layout.topMargin: 20
FluButton{
anchors.verticalCenter: parent.verticalCenter
Layout.topMargin: 20
text:"Custom Content Dialog"
onClicked: {
custom_btn_dialog.open()
}
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluContentDialog{
id:dialog
title:"友情提示"
message:"数据正在加载中,请稍等..."
negativeText:"取消加载"
contentDelegate: Component{
Item{
width: parent.width
height: 80
FluProgressRing{
anchors.centerIn: parent
}
}
}
onNegativeClicked:{
showSuccess("点击取消按钮")
}
positiveText:"确定"
onPositiveClicked:{
showSuccess("点击确定按钮")
}
dialog.open()'
}
FluContentDialog{
id:custom_btn_dialog
title:"友情提示"
message:"数据正在加载中,请稍等..."
negativeText:"取消加载"
contentDelegate: Component{
Item{
width: parent.width
height: 80
FluProgressRing{
anchors.centerIn: parent
}
}
}
onNegativeClicked:{
showSuccess("点击取消按钮")
}
positiveText:"确定"
onPositiveClicked:{
showSuccess("点击确定按钮")
}
}
} }

View File

@ -65,6 +65,20 @@ FluContentPage{
.go(callable) .go(callable)
} }
} }
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Head"
onClicked: {
text_info.text = ""
FluNetwork.head("https://httpbingo.org/head")
.addQuery("name","孙悟空")
.addQuery("age",500)
.addQuery("address","花果山水帘洞")
.bind(root)
.go(callable)
}
}
FluButton{ FluButton{
implicitWidth: parent.width implicitWidth: parent.width
implicitHeight: 36 implicitHeight: 36
@ -281,6 +295,21 @@ FluContentPage{
.go(callable) .go(callable)
} }
} }
FluButton{
implicitWidth: parent.width
implicitHeight: 36
text: "Open Log"
onClicked: {
text_info.text = ""
FluNetwork.postJson("https://httpbingo.org/post")
.add("name","孙悟空")
.add("age",500)
.add("address","花果山水帘洞")
.openLog(true)
.bind(root)
.go(callable)
}
}
FluButton{ FluButton{
implicitWidth: parent.width implicitWidth: parent.width
implicitHeight: 36 implicitHeight: 36

View File

@ -59,22 +59,6 @@ FluScrollablePage{
} }
} }
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 50
paddings: 10
FluCheckBox{
text:"V-Sync"
checked: FluApp.vsync
anchors.verticalCenter: parent.verticalCenter
onClicked: {
FluApp.vsync = !FluApp.vsync
dialog_restart.open()
}
}
}
FluArea{ FluArea{
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20

View File

@ -0,0 +1,30 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
import "qrc:///example/qml/component"
FluScrollablePage{
title:"ShortcutPicker"
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 100
paddings: 10
FluShortcutPicker{
anchors.verticalCenter: parent.verticalCenter
}
}
CodeExpander{
Layout.fillWidth: true
Layout.topMargin: -1
code:'FluShortcutPicker{
}'
}
}

View File

@ -16,14 +16,13 @@ FluWindow {
id:window id:window
title: "FluentUI" title: "FluentUI"
width: 1000 width: 960
height: 640 height: 600
minimumWidth: 520 minimumWidth: 520
minimumHeight: 200 minimumHeight: 200
launchMode: FluWindowType.SingleTask launchMode: FluWindowType.SingleTask
fitsAppBarWindows: true fitsAppBarWindows: true
appBar: FluAppBar { appBar: FluAppBar {
width: window.width
height: 30 height: 30
darkText: Lang.dark_mode darkText: Lang.dark_mode
showDark: true showDark: true
@ -45,8 +44,16 @@ FluWindow {
} }
onFirstVisible: { onFirstVisible: {
timer_tour_delay.restart()
}
Timer{
id:timer_tour_delay
interval: 200
onTriggered: {
tour.open() tour.open()
} }
}
Component.onCompleted: { Component.onCompleted: {
checkUpdate(true) checkUpdate(true)
@ -80,6 +87,14 @@ FluWindow {
} }
} }
Timer{
id:timer_window_hide_delay
interval: 150
onTriggered: {
window.hide()
}
}
FluContentDialog{ FluContentDialog{
id:dialog_close id:dialog_close
title:"退出" title:"退出"
@ -87,8 +102,8 @@ FluWindow {
negativeText:"最小化" negativeText:"最小化"
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.NeutralButton | FluContentDialogType.PositiveButton buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.NeutralButton | FluContentDialogType.PositiveButton
onNegativeClicked: { onNegativeClicked: {
window.hide()
system_tray.showMessage("友情提示","FluentUI已隐藏至托盘,点击托盘可再次激活窗口"); system_tray.showMessage("友情提示","FluentUI已隐藏至托盘,点击托盘可再次激活窗口");
timer_window_hide_delay.restart()
} }
positiveText:"退出" positiveText:"退出"
neutralText:"取消" neutralText:"取消"
@ -186,7 +201,12 @@ FluWindow {
pageMode: FluNavigationViewType.NoStack pageMode: FluNavigationViewType.NoStack
items: ItemsOriginal items: ItemsOriginal
footerItems:ItemsFooter footerItems:ItemsFooter
topPadding:FluTools.isMacos() ? 20 : 0 topPadding:{
if(window.useSystemAppBar){
return 0
}
return FluTools.isMacos() ? 20 : 0
}
displayMode:viewmodel_settings.displayMode displayMode:viewmodel_settings.displayMode
logo: "qrc:/example/res/image/favicon.ico" logo: "qrc:/example/res/image/favicon.ico"
title:"FluentUI" title:"FluentUI"
@ -223,7 +243,7 @@ FluWindow {
id:com_reveal id:com_reveal
CircularReveal{ CircularReveal{
id:reveal id:reveal
target:window.contentItem target:window.layoutContainer()
anchors.fill: parent anchors.fill: parent
onAnimationFinished:{ onAnimationFinished:{
//动画结束后释放资源 //动画结束后释放资源
@ -248,8 +268,11 @@ FluWindow {
if(!FluTheme.enableAnimation || window.fitsAppBarWindows === false){ if(!FluTheme.enableAnimation || window.fitsAppBarWindows === false){
changeDark() changeDark()
}else{ }else{
if(loader_reveal.sourceComponent){
return
}
loader_reveal.sourceComponent = com_reveal loader_reveal.sourceComponent = com_reveal
var target = window.contentItem var target = window.layoutContainer()
var pos = button.mapToItem(target,0,0) var pos = button.mapToItem(target,0,0)
var mouseX = pos.x var mouseX = pos.x
var mouseY = pos.y var mouseY = pos.y

View File

@ -5,10 +5,11 @@
CircularReveal::CircularReveal(QQuickItem* parent) : QQuickPaintedItem(parent) CircularReveal::CircularReveal(QQuickItem* parent) : QQuickPaintedItem(parent)
{ {
_anim = new QPropertyAnimation(this, "radius", this);
setVisible(false); setVisible(false);
_anim.setDuration(333); _anim->setDuration(333);
_anim.setEasingCurve(QEasingCurve::OutCubic); _anim->setEasingCurve(QEasingCurve::OutCubic);
connect(&_anim, &QPropertyAnimation::finished,this,[=](){ connect(_anim, &QPropertyAnimation::finished,this,[=](){
update(); update();
setVisible(false); setVisible(false);
Q_EMIT animationFinished(); Q_EMIT animationFinished();
@ -31,8 +32,8 @@ void CircularReveal::paint(QPainter* painter)
} }
void CircularReveal::start(int w,int h,const QPoint& center,int radius){ void CircularReveal::start(int w,int h,const QPoint& center,int radius){
_anim.setStartValue(0); _anim->setStartValue(0);
_anim.setEndValue(radius); _anim->setEndValue(radius);
_center = center; _center = center;
_grabResult = _target->grabToImage(QSize(w,h)); _grabResult = _target->grabToImage(QSize(w,h));
connect(_grabResult.data(), &QQuickItemGrabResult::ready, this, &CircularReveal::handleGrabResult); connect(_grabResult.data(), &QQuickItemGrabResult::ready, this, &CircularReveal::handleGrabResult);
@ -43,5 +44,5 @@ void CircularReveal::handleGrabResult(){
update(); update();
setVisible(true); setVisible(true);
Q_EMIT imageChanged(); Q_EMIT imageChanged();
_anim.start(); _anim->start();
} }

View File

@ -20,8 +20,8 @@ public:
Q_SIGNAL void animationFinished(); Q_SIGNAL void animationFinished();
Q_SLOT void handleGrabResult(); Q_SLOT void handleGrabResult();
private: private:
QPropertyAnimation* _anim = nullptr;
QImage _source; QImage _source;
QPropertyAnimation _anim = QPropertyAnimation(this, "radius", this);
QPoint _center; QPoint _center;
QSharedPointer<QQuickItemGrabResult> _grabResult; QSharedPointer<QQuickItemGrabResult> _grabResult;
}; };

204
example/src/helper/Log.cpp Normal file
View File

@ -0,0 +1,204 @@
#include "Log.h"
#include <QtCore/qdebug.h>
#include <QtCore/qfile.h>
#include <QtCore/qtextstream.h>
#include <QGuiApplication>
#include <iostream>
#include <QDateTime>
#include <QStandardPaths>
#include <QDir>
#include <QThread>
#include <QSettings>
#include <QRegularExpression>
#include "Version.h"
#ifdef WIN32
#include <process.h>
#else
#include <unistd.h>
#endif
#ifndef QT_ENDL
# if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
# define QT_ENDL Qt::endl
# else
# define QT_ENDL endl
# endif
#endif
static QString g_app = {};
static QString g_file_path= {};
static bool g_logError = false;
static std::unique_ptr<QFile> g_logFile = nullptr;
static std::unique_ptr<QTextStream> g_logStream = nullptr;
static int g_logLevel = 4;
std::map<QtMsgType, int> logLevelMap = {
{QtFatalMsg,0},
{QtCriticalMsg,1},
{QtWarningMsg,2},
{QtInfoMsg,3},
{QtDebugMsg,4}
};
QString Log::prettyProductInfoWrapper()
{
auto productName = QSysInfo::prettyProductName();
#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
#if defined(Q_OS_MACOS)
auto macosVersionFile = QString::fromUtf8("/System/Library/CoreServices/.SystemVersionPlatform.plist");
auto fi = QFileInfo (macosVersionFile);
if (fi.exists() && fi.isReadable()) {
auto plistFile = QFile(macosVersionFile);
plistFile.open(QIODevice::ReadOnly);
while (!plistFile.atEnd()) {
auto line = plistFile.readLine();
if (line.contains("ProductUserVisibleVersion")) {
auto nextLine = plistFile.readLine();
if (nextLine.contains("<string>")) {
QRegularExpression re(QString::fromUtf8("\\s*<string>(.*)</string>"));
auto matches = re.match(QString::fromUtf8(nextLine));
if (matches.hasMatch()) {
productName = QString::fromUtf8("macOS ") + matches.captured(1);
break;
}
}
}
}
}
#endif
#endif
#if defined(Q_OS_WIN)
QSettings regKey {QString::fromUtf8("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), QSettings::NativeFormat};
if (regKey.contains(QString::fromUtf8("CurrentBuildNumber"))) {
auto buildNumber = regKey.value(QString::fromUtf8("CurrentBuildNumber")).toInt();
if (buildNumber > 0) {
if (buildNumber < 9200) {
productName = QString::fromUtf8("Windows 7 build %1").arg(buildNumber);
}
else if (buildNumber < 10240) {
productName = QString::fromUtf8("Windows 8 build %1").arg(buildNumber);
}
else if (buildNumber < 22000) {
productName = QString::fromUtf8("Windows 10 build %1").arg(buildNumber);
}
else {
productName = QString::fromUtf8("Windows 11 build %1").arg(buildNumber);
}
}
}
#endif
return productName;
}
static inline void myMessageHandler(const QtMsgType type, const QMessageLogContext &context, const QString &message)
{
if(logLevelMap[type]>g_logLevel){
return;
}
if (!message.isEmpty()) {
QString levelName;
switch (type) {
case QtDebugMsg:
levelName = QStringLiteral("Debug");
break;
case QtInfoMsg:
levelName = QStringLiteral("Info");
break;
case QtWarningMsg:
levelName = QStringLiteral("Warning");
break;
case QtCriticalMsg:
levelName = QStringLiteral("Critical");
break;
case QtFatalMsg:
levelName = QStringLiteral("Fatal");
break;
}
QString fileAndLineLogStr;
if(context.file){
std::string strFileTmp = context.file;
const char* ptr = strrchr(strFileTmp.c_str(), '/');
if (nullptr != ptr) {
char fn[512] = {0};
sprintf(fn, "%s", ptr + 1);
strFileTmp = fn;
}
const char* ptrTmp = strrchr(strFileTmp.c_str(), '\\');
if (nullptr != ptrTmp) {
char fn[512] = {0};
sprintf(fn, "%s", ptrTmp + 1);
strFileTmp = fn;
}
fileAndLineLogStr = QString::fromStdString("[%1:%2]").arg(QString::fromStdString(strFileTmp),QString::number(context.line));
}
const QString finalMessage = QString::fromStdString("%1[%2]%3[%4]:%5").arg(
QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss.zzz"),
levelName,
fileAndLineLogStr,
QString::number(reinterpret_cast<quintptr>(QThread::currentThreadId())),
message);
if ((type == QtInfoMsg) || (type == QtDebugMsg)) {
std::cout << qPrintable(finalMessage) << std::endl;
} else {
std::cerr << qPrintable(finalMessage) << std::endl;
}
if (g_logError) {
return;
}
if (!g_logFile) {
g_logFile = std::make_unique<QFile>(g_file_path);
if (!g_logFile->open(QFile::WriteOnly | QFile::Text | QFile::Append)) {
std::cerr << "Can't open file to write: " << qPrintable(g_logFile->errorString()) << std::endl;
g_logFile.reset();
g_logError = true;
return;
}
}
if (!g_logStream) {
g_logStream = std::make_unique<QTextStream>();
g_logStream->setDevice(g_logFile.get());
}
(*g_logStream) << finalMessage << QT_ENDL;
g_logStream->flush();
}
}
void Log::setup(const QString &app)
{
Q_ASSERT(!app.isEmpty());
if (app.isEmpty()) {
return;
}
static bool once = false;
if (once) {
return;
}
once = true;
g_app = app;
const QString logFileName = QString("%1_%2.log").arg(g_app,QDateTime::currentDateTime().toString("yyyyMMdd"));
const QString logDirPath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)+"/log";
const QDir logDir(logDirPath);
if(!logDir.exists()){
logDir.mkpath(logDirPath);
}
g_file_path = logDir.filePath(logFileName);
qInstallMessageHandler(myMessageHandler);
qInfo()<<"===================================================";
qInfo()<<"[AppName]"<<g_app;
qInfo()<<"[AppVersion]"<<APPLICATION_VERSION;
#ifdef WIN32
qInfo()<<"[ProcessId]"<<QString::number(_getpid());
#else
qInfo()<<"[ProcessId]"<<QString::number(getpid());
#endif
qInfo()<<"[GitHashCode]"<<COMMIT_HASH;
qInfo()<<"[DeviceInfo]";
qInfo()<<" [DeviceId]"<<QSysInfo::machineUniqueId();
qInfo()<<" [Manufacturer]"<<prettyProductInfoWrapper();
qInfo()<<" [CPU_ABI]"<<QSysInfo::currentCpuArchitecture();
qInfo()<<"[LOG_LEVEL]"<<g_logLevel;
qInfo()<<"[LOG_PATH]"<<g_file_path;
qInfo()<<"===================================================";
}

11
example/src/helper/Log.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef LOG_H
#define LOG_H
#include <QtCore/qstring.h>
namespace Log
{
QString prettyProductInfoWrapper();
void setup(const QString &app);
}
#endif // LOG_H

View File

@ -12,23 +12,15 @@ SettingsHelper::~SettingsHelper() = default;
void SettingsHelper::save(const QString& key,QVariant val) void SettingsHelper::save(const QString& key,QVariant val)
{ {
QByteArray data = {}; m_settings->setValue(key, val);
QDataStream stream(&data, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_6);
stream << val;
m_settings->setValue(key, data);
} }
QVariant SettingsHelper::get(const QString& key,QVariant def){ QVariant SettingsHelper::get(const QString& key,QVariant def){
const QByteArray data = m_settings->value(key).toByteArray(); QVariant data = m_settings->value(key);
if (data.isEmpty()) { if (!data.isNull() && data.isValid()) {
return def; return data;
} }
QDataStream stream(data); return def;
stream.setVersion(QDataStream::Qt_5_6);
QVariant val;
stream >> val;
return val;
} }
void SettingsHelper::init(char *argv[]){ void SettingsHelper::init(char *argv[]){
@ -36,6 +28,5 @@ void SettingsHelper::init(char *argv[]){
const QFileInfo fileInfo(applicationPath); const QFileInfo fileInfo(applicationPath);
const QString iniFileName = fileInfo.completeBaseName() + ".ini"; const QString iniFileName = fileInfo.completeBaseName() + ".ini";
const QString iniFilePath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/" + iniFileName; const QString iniFilePath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/" + iniFileName;
qDebug()<<"Application configuration file path->"<<iniFilePath;
m_settings.reset(new QSettings(iniFilePath, QSettings::IniFormat)); m_settings.reset(new QSettings(iniFilePath, QSettings::IniFormat));
} }

View File

@ -20,13 +20,11 @@ public:
~SettingsHelper() override; ~SettingsHelper() override;
void init(char *argv[]); void init(char *argv[]);
Q_INVOKABLE void saveRender(const QVariant& render){save("render",render);} Q_INVOKABLE void saveRender(const QVariant& render){save("render",render);}
Q_INVOKABLE QVariant getRender(){return get("render");} Q_INVOKABLE QString getRender(){return get("render").toString();}
Q_INVOKABLE void saveDarkMode(int darkModel){save("darkMode",darkModel);} Q_INVOKABLE void saveDarkMode(int darkModel){save("darkMode",darkModel);}
Q_INVOKABLE QVariant getDarkMode(){return get("darkMode",QVariant(0));} Q_INVOKABLE int getDarkMode(){return get("darkMode",QVariant(0)).toInt();}
Q_INVOKABLE void saveVsync(bool vsync){save("vsync",vsync);}
Q_INVOKABLE QVariant getVsync(){return get("vsync",QVariant(true));}
Q_INVOKABLE void saveUseSystemAppBar(bool useSystemAppBar){save("useSystemAppBar",useSystemAppBar);} Q_INVOKABLE void saveUseSystemAppBar(bool useSystemAppBar){save("useSystemAppBar",useSystemAppBar);}
Q_INVOKABLE QVariant getUseSystemAppBar(){return get("useSystemAppBar",QVariant(false));} Q_INVOKABLE bool getUseSystemAppBar(){return get("useSystemAppBar",QVariant(false)).toBool();}
private: private:
void save(const QString& key,QVariant val); void save(const QString& key,QVariant val);
QVariant get(const QString& key,QVariant def={}); QVariant get(const QString& key,QVariant def={});

View File

@ -9,6 +9,7 @@
#include <QtQml/qqmlextensionplugin.h> #include <QtQml/qqmlextensionplugin.h>
#include <QLoggingCategory> #include <QLoggingCategory>
#include "AppInfo.h" #include "AppInfo.h"
#include "helper/Log.h"
#include "src/component/CircularReveal.h" #include "src/component/CircularReveal.h"
#include "src/component/FileWatcher.h" #include "src/component/FileWatcher.h"
#include "src/component/FpsItem.h" #include "src/component/FpsItem.h"
@ -23,7 +24,18 @@ Q_IMPORT_QML_PLUGIN(FluentUIPlugin)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy); qputenv("QT_QUICK_CONTROLS_STYLE","Basic");
#ifdef Q_OS_LINUX
//fix bug UOSv20 does not print logs
qputenv("QT_LOGGING_RULES","");
//fix bug UOSv20 v-sync does not work
qputenv("QSG_RENDER_LOOP","basic");
#endif
QGuiApplication::setOrganizationName("ZhuZiChu");
QGuiApplication::setOrganizationDomain("https://zhuzichu520.github.io");
QGuiApplication::setApplicationName("FluentUI");
SettingsHelper::getInstance()->init(argv);
Log::setup("example");
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
@ -31,11 +43,6 @@ int main(int argc, char *argv[])
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif #endif
#endif #endif
qputenv("QT_QUICK_CONTROLS_STYLE","Basic");
QGuiApplication::setOrganizationName("ZhuZiChu");
QGuiApplication::setOrganizationDomain("https://zhuzichu520.github.io");
QGuiApplication::setApplicationName("FluentUI");
SettingsHelper::getInstance()->init(argv);
if(SettingsHelper::getInstance()->getRender()=="software"){ if(SettingsHelper::getInstance()->getRender()=="software"){
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
QQuickWindow::setGraphicsApi(QSGRendererInterface::Software); QQuickWindow::setGraphicsApi(QSGRendererInterface::Software);
@ -53,7 +60,6 @@ int main(int argc, char *argv[])
#ifdef FLUENTUI_BUILD_STATIC_LIB #ifdef FLUENTUI_BUILD_STATIC_LIB
FluentUI::getInstance()->registerTypes(&engine); FluentUI::getInstance()->registerTypes(&engine);
#endif #endif
qDebug()<<engine.importPathList();
qmlRegisterType<CircularReveal>("example", 1, 0, "CircularReveal"); qmlRegisterType<CircularReveal>("example", 1, 0, "CircularReveal");
qmlRegisterType<FileWatcher>("example", 1, 0, "FileWatcher"); qmlRegisterType<FileWatcher>("example", 1, 0, "FileWatcher");
qmlRegisterType<FpsItem>("example", 1, 0, "FpsItem"); qmlRegisterType<FpsItem>("example", 1, 0, "FpsItem");

Submodule framelesshelper deleted from 49c72fb4f8

View File

@ -1,16 +1,14 @@
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
if (FLUENTUI_BUILD_STATIC_LIB AND (QT_VERSION VERSION_GREATER_EQUAL "6.2")) if (FLUENTUI_BUILD_STATIC_LIB AND (QT_VERSION VERSION_GREATER_EQUAL "6.2"))
project(fluentui LANGUAGES CXX) project(fluentui VERSION 1.0)
else() else()
project(fluentuiplugin LANGUAGES CXX) project(fluentuiplugin VERSION 1.0)
endif() endif()
#配置通用编译 #配置通用编译
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(APPLE)
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
endif()
if (FLUENTUI_BUILD_STATIC_LIB) if (FLUENTUI_BUILD_STATIC_LIB)
add_definitions(-DFLUENTUI_BUILD_STATIC_LIB) add_definitions(-DFLUENTUI_BUILD_STATIC_LIB)
@ -120,11 +118,14 @@ else()
) )
endif() endif()
target_compile_definitions(${PROJECT_NAME}
PRIVATE
HAVE_CONFIG_H
)
#去掉mingw生成的动态库libxxx前缀lib不去掉前缀会导致 module "FluentUI" plugin "fluentuiplugin" not found #去掉mingw生成的动态库libxxx前缀lib不去掉前缀会导致 module "FluentUI" plugin "fluentuiplugin" not found
if(MINGW) if(MINGW)
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "") set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX ".debug")
endif() endif()
#MSVC Debug 添加后缀d与Qt插件风格保持一致 #MSVC Debug 添加后缀d与Qt插件风格保持一致
@ -137,9 +138,6 @@ target_link_libraries(${PROJECT_NAME} PUBLIC
Qt${QT_VERSION_MAJOR}::CorePrivate Qt${QT_VERSION_MAJOR}::CorePrivate
Qt${QT_VERSION_MAJOR}::QuickPrivate Qt${QT_VERSION_MAJOR}::QuickPrivate
Qt${QT_VERSION_MAJOR}::QmlPrivate Qt${QT_VERSION_MAJOR}::QmlPrivate
ZXing
FramelessHelper::Core
FramelessHelper::Quick
) )
#安装 #安装

View File

@ -8,13 +8,8 @@
#include <QUuid> #include <QUuid>
#include <QFontDatabase> #include <QFontDatabase>
#include <QClipboard> #include <QClipboard>
#include <FramelessHelper/Quick/framelessquickmodule.h>
#include <FramelessHelper/Core/private/framelessconfig_p.h>
FRAMELESSHELPER_USE_NAMESPACE
FluApp::FluApp(QObject *parent):QObject{parent}{ FluApp::FluApp(QObject *parent):QObject{parent}{
connect(this,&FluApp::useSystemAppBarChanged,this,[=]{FramelessConfig::instance()->set(Global::Option::UseSystemAppBar,_useSystemAppBar);});
vsync(true); vsync(true);
useSystemAppBar(false); useSystemAppBar(false);
} }
@ -24,11 +19,10 @@ FluApp::~FluApp(){
void FluApp::init(QObject *application){ void FluApp::init(QObject *application){
this->_application = application; this->_application = application;
FramelessHelper::Quick::initialize(); QJSEngine * jsEngine = qjsEngine(_application);
FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial); std::string jsFunction = R"( (function () { console.log("FluentUI");}) )";
FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow); QJSValue function = jsEngine->evaluate(QString::fromStdString(jsFunction));
QQmlEngine *engine = qmlEngine(_application); jsEngine->globalObject().setProperty("__fluentui",function);
FramelessHelper::Quick::registerTypes(engine);
} }
void FluApp::run(){ void FluApp::run(){

View File

@ -22,6 +22,7 @@ class FluApp : public QObject
Q_PROPERTY_AUTO(QString,initialRoute); Q_PROPERTY_AUTO(QString,initialRoute);
Q_PROPERTY_AUTO(QJsonObject,routes); Q_PROPERTY_AUTO(QJsonObject,routes);
Q_PROPERTY_AUTO(bool,useSystemAppBar); Q_PROPERTY_AUTO(bool,useSystemAppBar);
Q_PROPERTY_AUTO(QString,windowIcon);
QML_NAMED_ELEMENT(FluApp) QML_NAMED_ELEMENT(FluApp)
QML_SINGLETON QML_SINGLETON
private: private:

256
src/FluFramelessHelper.cpp Normal file
View File

@ -0,0 +1,256 @@
#include "FluFramelessHelper.h"
#include <QGuiApplication>
#include <QOperatingSystemVersion>
#ifdef Q_OS_WIN
#pragma comment (lib,"user32.lib")
#pragma comment (lib,"dwmapi.lib")
#include <windows.h>
#include <dwmapi.h>
static inline QByteArray qtNativeEventType()
{
static const auto result = "windows_generic_MSG";
return result;
}
static inline bool isCompositionEnabled(){
typedef HRESULT (WINAPI* DwmIsCompositionEnabledPtr)(BOOL *pfEnabled);
HMODULE module = LoadLibraryW(L"dwmapi.dll");
if (module)
{
BOOL composition_enabled = false;
DwmIsCompositionEnabledPtr dwm_is_composition_enabled;
dwm_is_composition_enabled= reinterpret_cast<DwmIsCompositionEnabledPtr>(GetProcAddress(module, "DwmIsCompositionEnabled"));
if (dwm_is_composition_enabled)
{
dwm_is_composition_enabled(&composition_enabled);
}
return composition_enabled;
}
return false;
}
static inline void showShadow(HWND hwnd){
if(isCompositionEnabled()){
const MARGINS shadow = { 1, 1, 1, 1 };
typedef HRESULT (WINAPI* DwmExtendFrameIntoClientAreaPtr)(HWND hWnd, const MARGINS *pMarInset);
HMODULE module = LoadLibraryW(L"dwmapi.dll");
if (module)
{
DwmExtendFrameIntoClientAreaPtr dwm_extendframe_into_client_area_;
dwm_extendframe_into_client_area_= reinterpret_cast<DwmExtendFrameIntoClientAreaPtr>(GetProcAddress(module, "DwmExtendFrameIntoClientArea"));
if (dwm_extendframe_into_client_area_)
{
dwm_extendframe_into_client_area_(hwnd, &shadow);
}
}
}else{
ULONG_PTR cNewStyle = GetClassLongPtr(hwnd, GCL_STYLE) | CS_DROPSHADOW;
SetClassLongPtr(hwnd, GCL_STYLE, cNewStyle);
}
}
#endif
FramelessEventFilter::FramelessEventFilter(QQuickWindow* window){
_window = window;
_current = window->winId();
}
bool FramelessEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result){
#ifdef Q_OS_WIN
if ((eventType != qtNativeEventType()) || !message || !result || !_window) {
return false;
}
const auto msg = static_cast<const MSG *>(message);
const HWND hwnd = msg->hwnd;
if (!hwnd) {
return false;
}
const qint64 wid = reinterpret_cast<qint64>(hwnd);
if(wid != _current){
return false;
}
const UINT uMsg = msg->message;
const WPARAM wParam = msg->wParam;
const LPARAM lParam = msg->lParam;
if (!msg || !hwnd)
{
return false;
}
if(uMsg == WM_WINDOWPOSCHANGING){
WINDOWPOS* wp = reinterpret_cast<WINDOWPOS*>(lParam);
if (wp != nullptr && (wp->flags & SWP_NOSIZE) == 0)
{
wp->flags |= SWP_NOCOPYBITS;
*result = DefWindowProc(hwnd, uMsg, wParam, lParam);
return true;
}
return false;
}else if(uMsg == WM_NCCALCSIZE){
*result = WVR_REDRAW;
return true;
}else if(uMsg == WM_NCPAINT){
if(!isCompositionEnabled()){
*result = WVR_REDRAW;
return true;
}
return false;
}else if(uMsg == WM_NCACTIVATE){
if(!isCompositionEnabled()){
*result = 1;
return true;
}
return false;
}
return false;
#endif
return false;
}
FluFramelessHelper::FluFramelessHelper(QObject *parent)
: QObject{parent}
{
}
void FluFramelessHelper::classBegin(){
}
void FluFramelessHelper::updateCursor(int edges){
switch (edges) {
case 0:
_window->setCursor(Qt::ArrowCursor);
break;
case Qt::LeftEdge:
case Qt::RightEdge:
_window->setCursor(Qt::SizeHorCursor);
break;
case Qt::TopEdge:
case Qt::BottomEdge:
_window->setCursor(Qt::SizeVerCursor);
break;
case Qt::LeftEdge | Qt::TopEdge:
case Qt::RightEdge | Qt::BottomEdge:
_window->setCursor(Qt::SizeFDiagCursor);
break;
case Qt::RightEdge | Qt::TopEdge:
case Qt::LeftEdge | Qt::BottomEdge:
_window->setCursor(Qt::SizeBDiagCursor);
break;
}
}
bool FluFramelessHelper::eventFilter(QObject *obj, QEvent *ev){
if (!_window.isNull() && _window->flags() & Qt::FramelessWindowHint) {
static int edges = 0;
const int margin = 8;
switch (ev->type()) {
case QEvent::MouseButtonPress:
if(edges!=0){
updateCursor(edges);
_window->startSystemResize(Qt::Edges(edges));
}
break;
case QEvent::MouseButtonRelease:
edges = 0;
updateCursor(edges);
break;
case QEvent::MouseMove: {
if(_window->visibility() == QWindow::Maximized || _window->visibility() == QWindow::FullScreen){
break;
}
if(_window->width() == _window->maximumWidth() && _window->width() == _window->minimumWidth() && _window->height() == _window->maximumHeight() && _window->height() == _window->minimumHeight()){
break;
}
QMouseEvent *event = static_cast<QMouseEvent*>(ev);
QPoint p =
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
event->pos();
#else
event->position().toPoint();
#endif
if(p.x() >= margin && p.x() <= (_window->width() - margin) && p.y() >= margin && p.y() <= (_window->height() - margin)){
if(edges != 0){
edges = 0;
updateCursor(edges);
}
break;
}
edges = 0;
if ( p.x() < margin ) {
edges |= Qt::LeftEdge;
}
if ( p.x() > (_window->width() - margin) ) {
edges |= Qt::RightEdge;
}
if ( p.y() < margin ) {
edges |= Qt::TopEdge;
}
if ( p.y() > (_window->height() - margin) ) {
edges |= Qt::BottomEdge;
}
updateCursor(edges);
break;
}
default:
break;
}
}
return QObject::eventFilter(obj, ev);
}
void FluFramelessHelper::componentComplete(){
auto o = parent();
while (nullptr != o) {
_window = (QQuickWindow*)o;
o = o->parent();
}
if(!_window.isNull()){
_window->setFlags(Qt::FramelessWindowHint|Qt::Window|Qt::WindowTitleHint|Qt::WindowMinMaxButtonsHint|Qt::WindowCloseButtonHint);
#ifdef Q_OS_WIN
_nativeEvent =new FramelessEventFilter(_window);
qApp->installNativeEventFilter(_nativeEvent);
HWND hwnd = reinterpret_cast<HWND>(_window->winId());
SetWindowPos(hwnd,nullptr,0,0,0,0,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE |SWP_FRAMECHANGED);
showShadow(hwnd);
#endif
_stayTop = QQmlProperty(_window,"stayTop");
_onStayTopChange();
_stayTop.connectNotifySignal(this,SLOT(_onStayTopChange()));
_screen = QQmlProperty(_window,"screen");
_screen.connectNotifySignal(this,SLOT(_onScreenChanged()));
_window->installEventFilter(this);
}
}
void FluFramelessHelper::_onScreenChanged(){
_window->update();
QGuiApplication::processEvents();
}
void FluFramelessHelper::_onStayTopChange(){
bool isStayTop = _stayTop.read().toBool();
#ifdef Q_OS_WIN
HWND hwnd = reinterpret_cast<HWND>(_window->winId());
DWORD style = GetWindowLongPtr(hwnd,GWL_STYLE);
SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME | WS_CAPTION &~ WS_SYSMENU);
if(isStayTop){
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}else{
SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
#else
_window->setFlag(Qt::WindowStaysOnTopHint,isStayTop);
#endif
}
FluFramelessHelper::~FluFramelessHelper(){
if (!_window.isNull()) {
_window->setFlags(Qt::Window);
#ifdef Q_OS_WIN
qApp->removeNativeEventFilter(_nativeEvent);
#endif
_window->removeEventFilter(this);
}
}

50
src/FluFramelessHelper.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef FLUFRAMELESSHELPER_H
#define FLUFRAMELESSHELPER_H
#include <QObject>
#include <QQuickWindow>
#include <QtQml/qqml.h>
#include <QAbstractNativeEventFilter>
#include <QQmlProperty>
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
using QT_NATIVE_EVENT_RESULT_TYPE = qintptr;
using QT_ENTER_EVENT_TYPE = QEnterEvent;
#else
using QT_NATIVE_EVENT_RESULT_TYPE = long;
using QT_ENTER_EVENT_TYPE = QEvent;
#endif
class FramelessEventFilter : public QAbstractNativeEventFilter
{
public:
FramelessEventFilter(QQuickWindow* window);
bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
public:
QQuickWindow* _window = nullptr;
qint64 _current = 0;
};
class FluFramelessHelper : public QObject, public QQmlParserStatus
{
Q_OBJECT
QML_NAMED_ELEMENT(FluFramelessHelper)
public:
explicit FluFramelessHelper(QObject *parent = nullptr);
~FluFramelessHelper();
void classBegin() override;
void componentComplete() override;
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
private:
void updateCursor(int edges);
Q_SLOT void _onStayTopChange();
Q_SLOT void _onScreenChanged();
private:
QPointer<QQuickWindow> _window = nullptr;
FramelessEventFilter* _nativeEvent = nullptr;
QQmlProperty _stayTop;
QQmlProperty _screen;
};
#endif // FLUFRAMELESSHELPER_H

View File

@ -54,6 +54,13 @@ int NetworkParams::getRetry(){
return FluNetwork::getInstance()->retry(); return FluNetwork::getInstance()->retry();
} }
bool NetworkParams::getOpenLog(){
if(!_openLog.isNull()){
return _openLog.toBool();
}
return FluNetwork::getInstance()->openLog();
}
DownloadParam::DownloadParam(QObject *parent) DownloadParam::DownloadParam(QObject *parent)
: QObject{parent} : QObject{parent}
{ {
@ -129,6 +136,11 @@ NetworkParams* NetworkParams::bind(QObject* target){
return this; return this;
} }
NetworkParams* NetworkParams::openLog(QVariant val){
_openLog = val;
return this;
}
QString NetworkParams::buildCacheKey(){ QString NetworkParams::buildCacheKey(){
QJsonObject obj; QJsonObject obj;
obj.insert("url",_url); obj.insert("url",_url);
@ -189,8 +201,8 @@ void FluNetwork::handle(NetworkParams* params,NetworkCallable* c){
QNetworkRequest request(url); QNetworkRequest request(url);
addHeaders(&request,params->_headerMap); addHeaders(&request,params->_headerMap);
QNetworkReply* reply; QNetworkReply* reply;
sendRequest(&manager,request,params,reply,callable); sendRequest(&manager,request,params,reply,i==0,callable);
if(!QPointer(qApp)){ if(!QPointer<QGuiApplication>(qApp)){
reply->deleteLater(); reply->deleteLater();
reply = nullptr; reply = nullptr;
return; return;
@ -215,22 +227,26 @@ void FluNetwork::handle(NetworkParams* params,NetworkCallable* c){
disconnect(conn_quit); disconnect(conn_quit);
} }
QString response; QString response;
if(params->_method == NetworkParams::METHOD_HEAD){
response = headerList2String(reply->rawHeaderPairs());
}else{
if(reply->isOpen()){ if(reply->isOpen()){
response = QString::fromUtf8(reply->readAll()); response = QString::fromUtf8(reply->readAll());
} }
QNetworkReply::NetworkError error = reply->error(); }
if(error == QNetworkReply::NoError){ int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if(httpStatus == 200){
if(!callable.isNull()){ if(!callable.isNull()){
if(params->_cacheMode != FluNetworkType::CacheMode::NoCache){ if(params->_cacheMode != FluNetworkType::CacheMode::NoCache){
saveResponse(cacheKey,response); saveResponse(cacheKey,response);
} }
callable->success(response); callable->success(response);
} }
printRequestEndLog(request,params,reply,response);
break; break;
}else{ }else{
if(i == params->getRetry()-1){ if(i == params->getRetry()-1){
if(!callable.isNull()){ if(!callable.isNull()){
int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if(params->_cacheMode == FluNetworkType::CacheMode::RequestFailedReadCache && cacheExists(cacheKey)){ if(params->_cacheMode == FluNetworkType::CacheMode::RequestFailedReadCache && cacheExists(cacheKey)){
if(!callable.isNull()){ if(!callable.isNull()){
callable->cache(readCache(cacheKey)); callable->cache(readCache(cacheKey));
@ -238,6 +254,7 @@ void FluNetwork::handle(NetworkParams* params,NetworkCallable* c){
} }
callable->error(httpStatus,reply->errorString(),response); callable->error(httpStatus,reply->errorString(),response);
} }
printRequestEndLog(request,params,reply,response);
} }
} }
reply->deleteLater(); reply->deleteLater();
@ -387,10 +404,28 @@ QString FluNetwork::getCacheFilePath(const QString& key){
return cacheDir.absoluteFilePath(key); return cacheDir.absoluteFilePath(key);
} }
void FluNetwork::sendRequest(QNetworkAccessManager* manager,QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,QPointer<NetworkCallable> callable){ QString FluNetwork::headerList2String(const QList<QNetworkReply::RawHeaderPair>& data){
QJsonObject object;
for (auto it = data.constBegin(); it != data.constEnd(); ++it) {
object.insert(QString(it->first),QString(it->second));
}
return QJsonDocument(object).toJson(QJsonDocument::Compact);
}
QString FluNetwork::map2String(const QMap<QString, QVariant>& map){
QStringList parameters;
for (auto it = map.constBegin(); it != map.constEnd(); ++it) {
parameters << QString("%1=%2").arg(it.key(), it.value().toString());
}
return parameters.join(" ");
}
void FluNetwork::sendRequest(QNetworkAccessManager* manager,QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,bool isFirst,QPointer<NetworkCallable> callable){
QByteArray verb = params->method2String().toUtf8(); QByteArray verb = params->method2String().toUtf8();
switch (params->_type) { switch (params->_type) {
case NetworkParams::TYPE_FORM:{ case NetworkParams::TYPE_FORM:{
bool isFormData = !params->_fileMap.isEmpty();
if(isFormData){
QHttpMultiPart *multiPart = new QHttpMultiPart(); QHttpMultiPart *multiPart = new QHttpMultiPart();
multiPart->setContentType(QHttpMultiPart::FormDataType); multiPart->setContentType(QHttpMultiPart::FormDataType);
for (const auto& each : params->_paramMap.toStdMap()) for (const auto& each : params->_paramMap.toStdMap())
@ -415,12 +450,24 @@ void FluNetwork::sendRequest(QNetworkAccessManager* manager,QNetworkRequest requ
} }
reply = manager->sendCustomRequest(request,verb,multiPart); reply = manager->sendCustomRequest(request,verb,multiPart);
multiPart->setParent(reply); multiPart->setParent(reply);
if(!params->_fileMap.isEmpty()){
connect(reply,&QNetworkReply::uploadProgress,reply,[callable](qint64 bytesSent, qint64 bytesTotal){ connect(reply,&QNetworkReply::uploadProgress,reply,[callable](qint64 bytesSent, qint64 bytesTotal){
if(!callable.isNull() && bytesSent!=0 && bytesTotal!=0){ if(!callable.isNull() && bytesSent!=0 && bytesTotal!=0){
callable->uploadProgress(bytesSent,bytesTotal); Q_EMIT callable->uploadProgress(bytesSent,bytesTotal);
} }
}); });
}else{
request.setHeader(QNetworkRequest::ContentTypeHeader, QString("application/x-www-form-urlencoded"));
QString value;
for (const auto& each : params->_paramMap.toStdMap())
{
value += QString("%1=%2").arg(each.first,each.second.toString());
value += "&";
}
if(!params->_paramMap.isEmpty()){
value.chop(1);
}
QByteArray data = value.toUtf8();
reply = manager->sendCustomRequest(request,verb,data);
} }
break; break;
} }
@ -458,6 +505,46 @@ void FluNetwork::sendRequest(QNetworkAccessManager* manager,QNetworkRequest requ
reply = manager->sendCustomRequest(request,verb); reply = manager->sendCustomRequest(request,verb);
break; break;
} }
if(isFirst){
printRequestStartLog(request,params);
}
}
void FluNetwork::printRequestStartLog(QNetworkRequest request,NetworkParams* params){
if(!params->getOpenLog()){
return;
}
qDebug()<<"<------"<<qUtf8Printable(request.header(QNetworkRequest::UserAgentHeader).toString())<<"Request Start ------>";
qDebug()<<qUtf8Printable(QString::fromStdString("<%1>").arg(params->method2String()))<<qUtf8Printable(params->_url);
auto contentType = request.header(QNetworkRequest::ContentTypeHeader).toString();
if(!contentType.isEmpty()){
qDebug()<<qUtf8Printable(QString::fromStdString("<Header> %1=%2").arg("Content-Type",contentType));
}
QList<QByteArray> headers = request.rawHeaderList();
for(const QByteArray& header:headers){
qDebug()<<qUtf8Printable(QString::fromStdString("<Header> %1=%2").arg(header,request.rawHeader(header)));
}
if(!params->_queryMap.isEmpty()){
qDebug()<<"<Query>"<<qUtf8Printable(map2String(params->_queryMap));
}
if(!params->_paramMap.isEmpty()){
qDebug()<<"<Param>"<<qUtf8Printable(map2String(params->_paramMap));
}
if(!params->_fileMap.isEmpty()){
qDebug()<<"<File>"<<qUtf8Printable(map2String(params->_fileMap));
}
if(!params->_body.isEmpty()){
qDebug()<<"<Body>"<<qUtf8Printable(params->_body);
}
}
void FluNetwork::printRequestEndLog(QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,const QString& response){
if(!params->getOpenLog()){
return;
}
qDebug()<<"<------"<<qUtf8Printable(request.header(QNetworkRequest::UserAgentHeader).toString())<<"Request End ------>";
qDebug()<<qUtf8Printable(QString::fromStdString("<%1>").arg(params->method2String()))<<qUtf8Printable(params->_url);
qDebug()<<"<Result>"<<qUtf8Printable(response);
} }
void FluNetwork::saveResponse(QString key,QString response){ void FluNetwork::saveResponse(QString key,QString response){
@ -471,6 +558,7 @@ void FluNetwork::saveResponse(QString key,QString response){
} }
void FluNetwork::addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>& headers){ void FluNetwork::addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>& headers){
request->setHeader(QNetworkRequest::UserAgentHeader,QString::fromStdString("Mozilla/5.0 %1/%2").arg(QGuiApplication::applicationName(),QGuiApplication::applicationVersion()));
QMapIterator<QString, QVariant> iter(headers); QMapIterator<QString, QVariant> iter(headers);
while (iter.hasNext()) while (iter.hasNext())
{ {
@ -494,6 +582,7 @@ FluNetwork::FluNetwork(QObject *parent): QObject{parent}
{ {
timeout(5000); timeout(5000);
retry(3); retry(3);
openLog(false);
cacheDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation).append(QDir::separator()).append("network")); cacheDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation).append(QDir::separator()).append("network"));
} }

View File

@ -7,6 +7,7 @@
#include <QJsonValue> #include <QJsonValue>
#include <QJSValue> #include <QJSValue>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkReply>
#include "Def.h" #include "Def.h"
#include "stdafx.h" #include "stdafx.h"
#include "singleton.h" #include "singleton.h"
@ -67,11 +68,13 @@ public:
Q_INVOKABLE NetworkParams* setCacheMode(int val); Q_INVOKABLE NetworkParams* setCacheMode(int val);
Q_INVOKABLE NetworkParams* toDownload(QString destPath,bool append = false); Q_INVOKABLE NetworkParams* toDownload(QString destPath,bool append = false);
Q_INVOKABLE NetworkParams* bind(QObject* target); Q_INVOKABLE NetworkParams* bind(QObject* target);
Q_INVOKABLE NetworkParams* openLog(QVariant val);
Q_INVOKABLE void go(NetworkCallable* result); Q_INVOKABLE void go(NetworkCallable* result);
QString buildCacheKey(); QString buildCacheKey();
QString method2String(); QString method2String();
int getTimeout(); int getTimeout();
int getRetry(); int getRetry();
bool getOpenLog();
public: public:
DownloadParam* _downloadParam = nullptr; DownloadParam* _downloadParam = nullptr;
QObject* _target = nullptr; QObject* _target = nullptr;
@ -85,6 +88,7 @@ public:
QMap<QString, QVariant> _fileMap; QMap<QString, QVariant> _fileMap;
int _timeout = -1; int _timeout = -1;
int _retry = -1; int _retry = -1;
QVariant _openLog;
int _cacheMode = FluNetworkType::CacheMode::NoCache; int _cacheMode = FluNetworkType::CacheMode::NoCache;
}; };
@ -94,6 +98,7 @@ class FluNetwork : public QObject
Q_PROPERTY_AUTO(int,timeout) Q_PROPERTY_AUTO(int,timeout)
Q_PROPERTY_AUTO(int,retry) Q_PROPERTY_AUTO(int,retry)
Q_PROPERTY_AUTO(QString,cacheDir) Q_PROPERTY_AUTO(QString,cacheDir)
Q_PROPERTY_AUTO(bool,openLog)
QML_NAMED_ELEMENT(FluNetwork) QML_NAMED_ELEMENT(FluNetwork)
QML_SINGLETON QML_SINGLETON
private: private:
@ -123,13 +128,17 @@ public:
void handle(NetworkParams* params,NetworkCallable* result); void handle(NetworkParams* params,NetworkCallable* result);
void handleDownload(NetworkParams* params,NetworkCallable* result); void handleDownload(NetworkParams* params,NetworkCallable* result);
private: private:
void sendRequest(QNetworkAccessManager* manager,QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,QPointer<NetworkCallable> callable); void sendRequest(QNetworkAccessManager* manager,QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,bool isFirst,QPointer<NetworkCallable> callable);
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>& headers); void addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>& headers);
void saveResponse(QString key,QString response); void saveResponse(QString key,QString response);
QString readCache(const QString& key); QString readCache(const QString& key);
bool cacheExists(const QString& key); bool cacheExists(const QString& key);
QString getCacheFilePath(const QString& key); QString getCacheFilePath(const QString& key);
QString map2String(const QMap<QString, QVariant>& map);
QString headerList2String(const QList<QNetworkReply::RawHeaderPair>& data);
void printRequestStartLog(QNetworkRequest request,NetworkParams* params);
void printRequestEndLog(QNetworkRequest request,NetworkParams* params,QNetworkReply*& reply,const QString& response);
public: public:
QJSValue _interceptor; QJSValue _interceptor;
}; };

View File

@ -11,26 +11,26 @@ FluTextStyle::FluTextStyle(QObject *parent):QObject{parent}{
QFont bodyStrong; QFont bodyStrong;
bodyStrong.setPixelSize(13); bodyStrong.setPixelSize(13);
bodyStrong.setBold(true); bodyStrong.setWeight(QFont::DemiBold);
BodyStrong(bodyStrong); BodyStrong(bodyStrong);
QFont subtitle; QFont subtitle;
subtitle.setPixelSize(20); subtitle.setPixelSize(20);
subtitle.setBold(true); subtitle.setWeight(QFont::DemiBold);
Subtitle(subtitle); Subtitle(subtitle);
QFont title; QFont title;
title.setPixelSize(28); title.setPixelSize(28);
title.setBold(true); title.setWeight(QFont::DemiBold);
Title(title); Title(title);
QFont titleLarge; QFont titleLarge;
titleLarge.setPixelSize(40); titleLarge.setPixelSize(40);
titleLarge.setBold(true); titleLarge.setWeight(QFont::DemiBold);
TitleLarge(titleLarge); TitleLarge(titleLarge);
QFont display; QFont display;
display.setPixelSize(68); display.setPixelSize(68);
display.setBold(true); display.setWeight(QFont::DemiBold);
Display(display); Display(display);
} }

View File

@ -175,3 +175,7 @@ QPoint FluTools::cursorPos(){
qint64 FluTools::currentTimestamp(){ qint64 FluTools::currentTimestamp(){
return QDateTime::currentMSecsSinceEpoch(); return QDateTime::currentMSecsSinceEpoch();
} }
QIcon FluTools::windowIcon(){
return QGuiApplication::windowIcon();
}

View File

@ -49,6 +49,7 @@ public:
Q_INVOKABLE bool isSoftware(); Q_INVOKABLE bool isSoftware();
Q_INVOKABLE qint64 currentTimestamp(); Q_INVOKABLE qint64 currentTimestamp();
Q_INVOKABLE QPoint cursorPos(); Q_INVOKABLE QPoint cursorPos();
Q_INVOKABLE QIcon windowIcon();
}; };
#endif // FLUTOOLS_H #endif // FLUTOOLS_H

View File

@ -16,6 +16,7 @@
#include "Screenshot.h" #include "Screenshot.h"
#include "FluRectangle.h" #include "FluRectangle.h"
#include "FluNetwork.h" #include "FluNetwork.h"
#include "FluFramelessHelper.h"
#include "QRCode.h" #include "QRCode.h"
void FluentUI::registerTypes(QQmlEngine *engine){ void FluentUI::registerTypes(QQmlEngine *engine){
@ -40,6 +41,7 @@ void FluentUI::registerTypes(const char *uri){
qmlRegisterType<FluRectangle>(uri,major,minor,"FluRectangle"); qmlRegisterType<FluRectangle>(uri,major,minor,"FluRectangle");
qmlRegisterType<NetworkCallable>(uri,major,minor,"FluNetworkCallable"); qmlRegisterType<NetworkCallable>(uri,major,minor,"FluNetworkCallable");
qmlRegisterType<NetworkParams>(uri,major,minor,"FluNetworkParams"); qmlRegisterType<NetworkParams>(uri,major,minor,"FluNetworkParams");
qmlRegisterType<FluFramelessHelper>(uri,major,minor,"FluFramelessHelper");
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/ColorPicker/ColorPicker.qml"),uri,major,minor,"ColorPicker"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/ColorPicker/ColorPicker.qml"),uri,major,minor,"ColorPicker");
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/ColorPicker/Content/Checkerboard.qml"),uri,major,minor,"Checkerboard"); qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/ColorPicker/Content/Checkerboard.qml"),uri,major,minor,"Checkerboard");
@ -159,7 +161,7 @@ void FluentUI::registerTypes(const char *uri){
void FluentUI::initializeEngine(QQmlEngine *engine, const char *uri){ void FluentUI::initializeEngine(QQmlEngine *engine, const char *uri){
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
QFont font; QFont font;
font.setFamily("Microsoft YaHei"); font.setFamily("微软雅黑");
QGuiApplication::setFont(font); QGuiApplication::setFont(font);
#endif #endif
FluApp* app = FluApp::getInstance(); FluApp* app = FluApp::getInstance();

View File

@ -1,10 +1,6 @@
#include "QRCode.h" #include "QRCode.h"
#include "BarcodeFormat.h" #include "qrcode/qrencode.h"
#include "BitMatrix.h"
#include "MultiFormatWriter.h"
using namespace ZXing;
QRCode::QRCode(QQuickItem* parent):QQuickPaintedItem(parent){ QRCode::QRCode(QQuickItem* parent):QQuickPaintedItem(parent){
color(QColor(0,0,0,255)); color(QColor(0,0,0,255));
@ -27,29 +23,35 @@ void QRCode::paint(QPainter* painter){
if(_text.isEmpty()){ if(_text.isEmpty()){
return; return;
} }
if(_text.length()>1108){ if(_text.length()>1024){
return; return;
} }
painter->save(); painter->save();
auto format = ZXing::BarcodeFormatFromString("QRCode"); QRcode *qrcode = QRcode_encodeString(_text.toUtf8().constData(), 2, QR_ECLEVEL_Q, QR_MODE_8, 1);
auto writer = MultiFormatWriter(format); qint32 w = width();
writer.setMargin(0); qint32 h = height();
writer.setEncoding(ZXing::CharacterSet::UTF8); qint32 qrcodeW = qrcode->width > 0 ? qrcode->width : 1;
auto matrix = writer.encode(_text.toUtf8().constData(), 0, 0); double scaleX = (double)w / (double)qrcodeW;
auto bitmap = ToMatrix<uint8_t>(matrix); double scaleY = (double)h / (double)qrcodeW;
auto image = QImage(bitmap.data(), bitmap.width(), bitmap.height(), bitmap.width(), QImage::Format::Format_Grayscale8).copy(); QImage image = QImage(w, h, QImage::Format_ARGB32);
QImage rgbImage = image.convertToFormat(QImage::Format_ARGB32); QPainter p(&image);
for (int y = 0; y < rgbImage.height(); ++y) { p.setBrush(_bgColor);
for (int x = 0; x < rgbImage.width(); ++x) { p.setPen(Qt::NoPen);
QRgb pixel = rgbImage.pixel(x, y); p.drawRect(0, 0, w, h);
if (qRed(pixel) == 0 && qGreen(pixel) == 0 && qBlue(pixel) == 0) { p.setBrush(_color);
rgbImage.setPixelColor(x, y, _color); for (qint32 y = 0; y < qrcodeW; y++)
} {
if (qRed(pixel) == 255 && qGreen(pixel) == 255 && qBlue(pixel) == 255) { for (qint32 x = 0; x < qrcodeW; x++)
rgbImage.setPixelColor(x, y, _bgColor); {
unsigned char b = qrcode->data[y*qrcodeW + x];
if (b & 0x01)
{
QRectF r(x * scaleX,y * scaleY, scaleX, scaleY);
p.drawRects(&r, 1);
} }
} }
} }
painter->drawImage(QRect(0, 0, static_cast<int>(width()), static_cast<int>(height())), rgbImage); QPixmap pixmap = QPixmap::fromImage(image);
painter->drawPixmap(QRect(0, 0, static_cast<int>(width()), static_cast<int>(height())), pixmap);
painter->restore(); painter->restore();
} }

View File

@ -34,11 +34,18 @@ Rectangle{
property bool isMac: FluTools.isMacos() property bool isMac: FluTools.isMacos()
property color borerlessColor : FluTheme.primaryColor property color borerlessColor : FluTheme.primaryColor
property var maxClickListener : function(){ property var maxClickListener : function(){
if(FluTools.isMacos()){
if (d.win.visibility === Window.FullScreen)
d.win.visibility = Window.Windowed
else
d.win.visibility = Window.FullScreen
}else{
if (d.win.visibility === Window.Maximized) if (d.win.visibility === Window.Maximized)
d.win.visibility = Window.Windowed d.win.visibility = Window.Windowed
else else
d.win.visibility = Window.Maximized d.win.visibility = Window.Maximized
} }
}
property var minClickListener: function(){ property var minClickListener: function(){
d.win.visibility = Window.Minimized d.win.visibility = Window.Minimized
} }
@ -74,14 +81,16 @@ Rectangle{
property bool isRestore: win && Window.Maximized === win.visibility property bool isRestore: win && Window.Maximized === win.visibility
property bool resizable: win && !(win.height === win.maximumHeight && win.height === win.minimumHeight && win.width === win.maximumWidth && win.width === win.minimumWidth) property bool resizable: win && !(win.height === win.maximumHeight && win.height === win.minimumHeight && win.width === win.maximumWidth && win.width === win.minimumWidth)
} }
TapHandler { MouseArea{
onTapped: if (tapCount === 2 && d.resizable) btn_maximize.clicked() anchors.fill: parent
gesturePolicy: TapHandler.DragThreshold onPositionChanged: {
d.win.startSystemMove()
}
onDoubleClicked: {
if(d.resizable){
btn_maximize.clicked()
}
} }
DragHandler {
target: null
grabPermissions: TapHandler.CanTakeOverFromAnything
onActiveChanged: if (active) { d.win.startSystemMove(); }
} }
Row{ Row{
anchors{ anchors{
@ -105,6 +114,49 @@ Rectangle{
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Component{
id:com_mac_buttons
RowLayout{
FluImageButton{
Layout.preferredHeight: 12
Layout.preferredWidth: 12
normalImage: "../Image/btn_close_normal.png"
hoveredImage: "../Image/btn_close_hovered.png"
pushedImage: "../Image/btn_close_pushed.png"
visible: showClose
onClicked: closeClickListener()
}
FluImageButton{
Layout.preferredHeight: 12
Layout.preferredWidth: 12
normalImage: "../Image/btn_min_normal.png"
hoveredImage: "../Image/btn_min_hovered.png"
pushedImage: "../Image/btn_min_pushed.png"
onClicked: minClickListener()
visible: showMinimize
}
FluImageButton{
Layout.preferredHeight: 12
Layout.preferredWidth: 12
normalImage: "../Image/btn_max_normal.png"
hoveredImage: "../Image/btn_max_hovered.png"
pushedImage: "../Image/btn_max_pushed.png"
onClicked: maxClickListener()
visible: d.resizable && showMaximize
}
}
}
FluLoader{
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 10
}
sourceComponent: isMac ? com_mac_buttons : undefined
}
RowLayout{ RowLayout{
anchors.right: parent.right anchors.right: parent.right
height: control.height height: control.height

View File

@ -6,8 +6,8 @@ Button {
property bool disabled: false property bool disabled: false
property string contentDescription: "" property string contentDescription: ""
property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1) property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1)
property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(246/255,246/255,246/255,1)
property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(244/255,244/255,244/255,1)
property color textColor: { property color textColor: {
if(FluTheme.dark){ if(FluTheme.dark){
if(!enabled){ if(!enabled){
@ -33,6 +33,7 @@ Button {
Accessible.onPressAction: control.clicked() Accessible.onPressAction: control.clicked()
id: control id: control
enabled: !disabled enabled: !disabled
verticalPadding: 0
horizontalPadding:12 horizontalPadding:12
font:FluTextStyle.Body font:FluTextStyle.Body
focusPolicy:Qt.TabFocus focusPolicy:Qt.TabFocus

View File

@ -4,25 +4,27 @@ import "./../JS/Chart.js" as Chart
Canvas { Canvas {
id: control id: control
property var window: Window.window
property var jsChart: undefined
property string chartType property string chartType
property var chartData property var chartData
property var chartOptions property var chartOptions
property double chartAnimationProgress: 0.1 property double chartAnimationProgress: 0.1
property int animationEasingType: Easing.InOutExpo property int animationEasingType: Easing.InOutExpo
property double animationDuration: 0 property double animationDuration: 300
property var memorizedContext
property var memorizedData
property var memorizedOptions
property alias animationRunning: chartAnimator.running property alias animationRunning: chartAnimator.running
signal animationFinished() signal animationFinished()
function animateToNewData() function animateToNewData()
{ {
chartAnimationProgress = 0.1; chartAnimationProgress = 0.1;
jsChart.update(); d.jsChart.update();
chartAnimator.restart(); chartAnimator.restart();
} }
QtObject{
id:d
property var jsChart: undefined
property var memorizedContext
property var memorizedData
property var memorizedOptions
}
MouseArea { MouseArea {
id: event id: event
anchors.fill: control anchors.fill: control
@ -48,17 +50,17 @@ Canvas {
mouseEvent.left = 0; mouseEvent.left = 0;
mouseEvent.top = 0; mouseEvent.top = 0;
mouseEvent.target = control; mouseEvent.target = control;
if(handler) { if(handler) {
handler(mouseEvent); handler(mouseEvent);
} }
control.requestPaint(); control.requestPaint();
} }
onClicked:(mouse)=> { onClicked:
(mouse)=> {
submitEvent(mouse, "click"); submitEvent(mouse, "click");
} }
onPositionChanged:(mouse)=> { onPositionChanged:
(mouse)=> {
submitEvent(mouse, "mousemove"); submitEvent(mouse, "mousemove");
} }
onExited: { onExited: {
@ -67,10 +69,12 @@ Canvas {
onEntered: { onEntered: {
submitEvent(undefined, "mouseenter"); submitEvent(undefined, "mouseenter");
} }
onPressed:(mouse)=> { onPressed:
(mouse)=> {
submitEvent(mouse, "mousedown"); submitEvent(mouse, "mousedown");
} }
onReleased:(mouse)=> { onReleased:
(mouse)=> {
submitEvent(mouse, "mouseup"); submitEvent(mouse, "mouseup");
} }
} }
@ -90,34 +94,25 @@ Canvas {
control.requestPaint(); control.requestPaint();
} }
onPaint: { onPaint: {
if(control.getContext('2d') !== null && memorizedContext !== control.getContext('2d') || memorizedData !== control.chartData || memorizedOptions !== control.chartOptions) { if(control.getContext('2d') !== null && d.memorizedContext !== control.getContext('2d') || d.memorizedData !== control.chartData || d.memorizedOptions !== control.chartOptions) {
var ctx = control.getContext('2d'); var ctx = control.getContext('2d');
d.jsChart = Chart.build(ctx, {type: control.chartType,data: control.chartData,options: control.chartOptions});
jsChart = Chart.build(ctx, { d.memorizedData = control.chartData ;
type: control.chartType, d.memorizedContext = control.getContext('2d');
data: control.chartData, d.memorizedOptions = control.chartOptions;
options: control.chartOptions d.jsChart.bindEvents(function(newHandler) {event.handler = newHandler;});
});
memorizedData = control.chartData ;
memorizedContext = control.getContext('2d');
memorizedOptions = control.chartOptions;
control.jsChart.bindEvents(function(newHandler) {event.handler = newHandler;});
chartAnimator.start(); chartAnimator.start();
} }
d.jsChart.draw(chartAnimationProgress);
jsChart.draw(chartAnimationProgress);
} }
onWidthChanged: { onWidthChanged: {
if(jsChart) { if(d.jsChart) {
jsChart.resize(); d.jsChart.resize();
} }
} }
onHeightChanged: { onHeightChanged: {
if(jsChart) { if(d.jsChart) {
jsChart.resize(); d.jsChart.resize();
} }
} }
} }

View File

@ -5,51 +5,37 @@ import QtQuick.Window 2.15
import FluentUI 1.0 import FluentUI 1.0
FluPopup { FluPopup {
id: popup id: control
property string title: "Title" property string title: ""
property string message: "Message" property string message: ""
property string neutralText: "Neutral" property string neutralText: "Neutral"
property string negativeText: "Negative" property string negativeText: "Negative"
property string positiveText: "Positive" property string positiveText: "Positive"
property alias messageTextFormart: text_message.textFormat property int messageTextFormart: Text.AutoText
property int delayTime: 100 property int delayTime: 100
property int buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
property var contentDelegate: Component{
Item{
}
}
property var onNeutralClickListener
property var onNegativeClickListener
property var onPositiveClickListener
signal neutralClicked signal neutralClicked
signal negativeClicked signal negativeClicked
signal positiveClicked signal positiveClicked
property int buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
focus: true
implicitWidth: 400 implicitWidth: 400
implicitHeight: text_title.height + sroll_message.height + layout_actions.height implicitHeight: layout_content.height
Rectangle { focus: true
id:layout_content Component{
anchors.fill: parent id:com_message
color: 'transparent'
radius:5
FluText{
id:text_title
font: FluTextStyle.TitleLarge
text:title
topPadding: 20
leftPadding: 20
rightPadding: 20
wrapMode: Text.WrapAnywhere
anchors{
top:parent.top
left: parent.left
right: parent.right
}
}
Flickable{ Flickable{
id:sroll_message id:sroll_message
contentHeight: text_message.height
contentWidth: width contentWidth: width
clip: true clip: true
anchors{
top:text_title.bottom
left: parent.left
right: parent.right
}
boundsBehavior:Flickable.StopAtBounds boundsBehavior:Flickable.StopAtBounds
contentHeight: text_message.height width: parent.width
height: Math.min(text_message.height,300) height: Math.min(text_message.height,300)
ScrollBar.vertical: FluScrollBar {} ScrollBar.vertical: FluScrollBar {}
FluText{ FluText{
@ -58,22 +44,47 @@ FluPopup {
wrapMode: Text.WrapAnywhere wrapMode: Text.WrapAnywhere
text:message text:message
width: parent.width width: parent.width
topPadding: 14 topPadding: 4
leftPadding: 20 leftPadding: 20
rightPadding: 20 rightPadding: 20
bottomPadding: 14 bottomPadding: 4
}
} }
} }
Rectangle {
id:layout_content
width: parent.width
height: layout_column.childrenRect.height
color: 'transparent'
radius:5
ColumnLayout{
id:layout_column
width: parent.width
FluText{
id:text_title
font: FluTextStyle.Title
text:title
topPadding: 20
leftPadding: 20
rightPadding: 20
wrapMode: Text.WrapAnywhere
}
FluLoader{
sourceComponent: com_message
Layout.fillWidth: true
Layout.preferredHeight: status===Loader.Ready ? item.height : 0
}
FluLoader{
sourceComponent: control.contentDelegate
Layout.fillWidth: true
Layout.preferredHeight: status===Loader.Ready ? item.height : 0
}
Rectangle{ Rectangle{
id:layout_actions id:layout_actions
height: 68 Layout.fillWidth: true
Layout.preferredHeight: 60
radius: 5 radius: 5
color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1) color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
anchors{
top:sroll_message.bottom
left: parent.left
right: parent.right
}
RowLayout{ RowLayout{
anchors anchors
{ {
@ -81,59 +92,65 @@ FluPopup {
margins: spacing margins: spacing
fill: parent fill: parent
} }
spacing: 15 spacing: 10
Item{
Layout.fillWidth: true
Layout.fillHeight: true
visible: control.buttonFlags&FluContentDialogType.NeutralButton
FluButton{ FluButton{
id:neutral_btn id:neutral_btn
text: neutralText
width: parent.width
anchors.centerIn: parent
onClicked: {
if(control.onNeutralClickListener){
control.onNeutralClickListener()
}else{
neutralClicked()
control.close()
}
}
}
}
Item{
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
visible: popup.buttonFlags&FluContentDialogType.NeutralButton visible: control.buttonFlags&FluContentDialogType.NegativeButton
text: neutralText
onClicked: {
popup.close()
timer_delay.targetFlags = FluContentDialogType.NeutralButton
timer_delay.restart()
}
}
FluButton{ FluButton{
id:negative_btn id:negative_btn
Layout.fillWidth: true width: parent.width
Layout.fillHeight: true anchors.centerIn: parent
visible: popup.buttonFlags&FluContentDialogType.NegativeButton
text: negativeText text: negativeText
onClicked: { onClicked: {
popup.close() if(control.onNegativeClickListener){
timer_delay.targetFlags = FluContentDialogType.NegativeButton control.onNegativeClickListener()
timer_delay.restart() }else{
negativeClicked()
control.close()
} }
} }
FluFilledButton{ }
id:positive_btn }
Item{
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
visible: popup.buttonFlags&FluContentDialogType.PositiveButton visible: control.buttonFlags&FluContentDialogType.PositiveButton
FluFilledButton{
id:positive_btn
text: positiveText text: positiveText
width: parent.width
anchors.centerIn: parent
onClicked: { onClicked: {
popup.close() if(control.onPositiveClickListener){
timer_delay.targetFlags = FluContentDialogType.PositiveButton control.onPositiveClickListener()
timer_delay.restart() }else{
}
}
}
}
}
Timer{
property int targetFlags
id:timer_delay
interval: popup.delayTime
onTriggered: {
if(targetFlags === FluContentDialogType.NegativeButton){
negativeClicked()
}
if(targetFlags === FluContentDialogType.NeutralButton){
neutralClicked()
}
if(targetFlags === FluContentDialogType.PositiveButton){
positiveClicked() positiveClicked()
control.close()
}
}
}
}
}
} }
} }
} }

View File

@ -7,8 +7,8 @@ Button {
property bool disabled: false property bool disabled: false
property string contentDescription: "" property string contentDescription: ""
property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1) property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1)
property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(246/255,246/255,246/255,1)
property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(244/255,244/255,244/255,1)
property color textColor: { property color textColor: {
if(FluTheme.dark){ if(FluTheme.dark){
if(!enabled){ if(!enabled){
@ -38,6 +38,7 @@ Button {
rightPadding:35 rightPadding:35
enabled: !disabled enabled: !disabled
focusPolicy:Qt.TabFocus focusPolicy:Qt.TabFocus
verticalPadding: 0
horizontalPadding:12 horizontalPadding:12
background: Rectangle{ background: Rectangle{
implicitWidth: 28 implicitWidth: 28

View File

@ -27,6 +27,7 @@ Button {
enabled: !disabled enabled: !disabled
focusPolicy:Qt.TabFocus focusPolicy:Qt.TabFocus
font:FluTextStyle.Body font:FluTextStyle.Body
verticalPadding: 0
horizontalPadding:12 horizontalPadding:12
background: Rectangle{ background: Rectangle{
implicitWidth: 28 implicitWidth: 28

View File

@ -0,0 +1,18 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
Button{
id:control
property string normalImage: ""
property string hoveredImage: ""
property string pushedImage: ""
background: Item{
implicitHeight: 12
implicitWidth: 12
BorderImage {
anchors.fill: parent
source: control.hovered ? (control.pressed ? control.pushedImage : control.hoveredImage ) : control.normalImage
}
}
}

View File

@ -21,14 +21,14 @@ Button {
if(d.checked){ if(d.checked){
return FluTheme.dark ? Qt.darker(normalColor,1.1) : Qt.lighter(normalColor,1.1) return FluTheme.dark ? Qt.darker(normalColor,1.1) : Qt.lighter(normalColor,1.1)
}else{ }else{
return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(246/255,246/255,246/255,1)
} }
} }
property color disableColor: { property color disableColor: {
if(d.checked){ if(d.checked){
return FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1) return FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1)
}else{ }else{
return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(244/255,244/255,244/255,1)
} }
} }
property color pressedColor: FluTheme.dark ? Qt.darker(normalColor,1.2) : Qt.lighter(normalColor,1.2) property color pressedColor: FluTheme.dark ? Qt.darker(normalColor,1.2) : Qt.lighter(normalColor,1.2)
@ -39,6 +39,7 @@ Button {
focusPolicy:Qt.TabFocus focusPolicy:Qt.TabFocus
id: control id: control
enabled: !disabled enabled: !disabled
verticalPadding: 0
horizontalPadding:12 horizontalPadding:12
background: FluClip{ background: FluClip{
implicitWidth: 28 implicitWidth: 28
@ -69,7 +70,7 @@ Button {
color: FluTheme.primaryColor color: FluTheme.primaryColor
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
Behavior on height{ Behavior on height{
enabled: control.progress !== 1 enabled: control.progress === 1
SequentialAnimation { SequentialAnimation {
PauseAnimation { PauseAnimation {
duration: FluTheme.enableAnimation ? 167 : 0 duration: FluTheme.enableAnimation ? 167 : 0

View File

@ -0,0 +1,231 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
FluIconButton {
id:control
property var current : ["Ctrl","Shift","A"]
property string title: "激活快捷键"
property string message: "按下组合键以更改此快捷键"
property string positiveText: "保存"
property string neutralText: "取消"
property string negativeText: "重置"
signal accepted()
QtObject{
id: d
function keyToString(key_code,shift = true)
{
switch(key_code)
{
case Qt.Key_Period: return ".";
case Qt.Key_Greater: return shift ? ">" : ".";
case Qt.Key_Comma: return ",";
case Qt.Key_Less: return shift ? "<" : ",";
case Qt.Key_Slash: return "/";
case Qt.Key_Question: return shift ? "?" : "/";
case Qt.Key_Semicolon: return ";";
case Qt.Key_Colon: return shift ? ":" : ";";
case Qt.Key_Apostrophe: return "'";
case Qt.Key_QuoteDbl: return shift ? "'" : "\"";
case Qt.Key_QuoteLeft: return "`";
case Qt.Key_AsciiTilde: return shift ? "~" : "`";
case Qt.Key_Minus: return "-";
case Qt.Key_Underscore: return shift ? "_" : "-";
case Qt.Key_Equal: return "=";
case Qt.Key_Plus: return shift ? "+" : "=";
case Qt.Key_BracketLeft: return "[";
case Qt.Key_BraceLeft: return shift ? "{" : "[";
case Qt.Key_BracketRight: return "]";
case Qt.Key_BraceRight: return shift ? "}" : "]";
case Qt.Key_Backslash: return "\\";
case Qt.Key_Bar: return shift ? "|" : "\\";
case Qt.Key_Up: return "Up";
case Qt.Key_Down: return "Down";
case Qt.Key_Right: return "Right";
case Qt.Key_Left: return "Left";
case Qt.Key_Space: return "Space";
case Qt.Key_PageDown: return "PgDown";
case Qt.Key_PageUp: return "PgUp";
case Qt.Key_0: return "0";
case Qt.Key_1: return "1";
case Qt.Key_2: return "2";
case Qt.Key_3: return "3";
case Qt.Key_4: return "4";
case Qt.Key_5: return "5";
case Qt.Key_6: return "6";
case Qt.Key_7: return "7";
case Qt.Key_8: return "8";
case Qt.Key_9: return "9";
case Qt.Key_Exclam: return shift ? "!" : "1";
case Qt.Key_At: return shift ? "@" : "2";
case Qt.Key_NumberSign: return shift ? "#" : "3";
case Qt.Key_Dollar: return shift ? "$" : "4";
case Qt.Key_Percent: return shift ? "%" : "5";
case Qt.Key_AsciiCircum: return shift ? "^" : "6";
case Qt.Key_Ampersand: return shift ? "&" : "7";
case Qt.Key_Asterisk: return shift ? "*" : "8";
case Qt.Key_ParenLeft: return shift ? "(" : "9";
case Qt.Key_ParenRight: return shift ? ")" : "0";
case Qt.Key_A: return "A";
case Qt.Key_B: return "B";
case Qt.Key_C: return "C";
case Qt.Key_D: return "D";
case Qt.Key_E: return "E";
case Qt.Key_F: return "F";
case Qt.Key_G: return "G";
case Qt.Key_H: return "H";
case Qt.Key_I: return "I";
case Qt.Key_J: return "J";
case Qt.Key_K: return "K";
case Qt.Key_L: return "L";
case Qt.Key_M: return "M";
case Qt.Key_N: return "N";
case Qt.Key_O: return "O";
case Qt.Key_P: return "P";
case Qt.Key_Q: return "Q";
case Qt.Key_R: return "R";
case Qt.Key_S: return "S";
case Qt.Key_T: return "T";
case Qt.Key_U: return "U";
case Qt.Key_V: return "V";
case Qt.Key_W: return "W";
case Qt.Key_X: return "X";
case Qt.Key_Y: return "Y";
case Qt.Key_Z: return "Z";
case Qt.Key_F1: return "F1";
case Qt.Key_F2: return "F2";
case Qt.Key_F3: return "F3";
case Qt.Key_F4: return "F4";
case Qt.Key_F5: return "F5";
case Qt.Key_F6: return "F6";
case Qt.Key_F7: return "F7";
case Qt.Key_F8: return "F8";
case Qt.Key_F9: return "F9";
case Qt.Key_F10: return "F10";
case Qt.Key_F11: return "F11";
case Qt.Key_F12: return "F12";
case Qt.Key_Home: return "Home";
case Qt.Key_End: return "End";
case Qt.Key_Insert: return "Insert";
case Qt.Key_Delete: return "Delete";
}
return "";
}
}
background: Rectangle{
border.color: FluTheme.dark ? "#505050" : "#DFDFDF"
border.width: 1
implicitHeight: 42
implicitWidth: layout_row.width+28
radius: control.radius
color:control.color
FluFocusRectangle{
visible: control.activeFocus
}
}
component ItemKey:Rectangle{
id:item_key_control
property string text : ""
color:FluTheme.primaryColor
width: Math.max(item_text.implicitWidth+12,28)
height: Math.max(item_text.implicitHeight,28)
radius: 4
Text{
id:item_text
color: FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1)
font.pixelSize: 13
text: item_key_control.text
anchors.centerIn: parent
}
}
Row{
id:layout_row
spacing: 5
anchors.centerIn: parent
Repeater{
model: control.current
delegate: ItemKey{
text: modelData
}
}
Item{
width: 3
height: 1
}
FluIcon{
iconSource: FluentIcons.EditMirrored
iconSize: 13
anchors{
verticalCenter: parent.verticalCenter
}
}
}
FluContentDialog{
id:content_dialog
property var keysModel: []
title: control.title
message: control.message
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton | FluContentDialogType.NeutralButton
positiveText: control.positiveText
neutralText: control.neutralText
negativeText: control.negativeText
onVisibleChanged: {
if(visible){
content_dialog.keysModel = control.current
}
}
onPositiveClicked: {
control.current = content_dialog.keysModel
control.accepted()
}
onNegativeClickListener: function(){
content_dialog.keysModel = control.current
}
contentDelegate: Component{
Item{
width: parent.width
height: 100
Component.onCompleted: {
forceActiveFocus()
}
Keys.enabled: true
Keys.onPressed:
(event)=>{
var keyNames = []
if (event.modifiers & Qt.AltModifier) {
keyNames.push("Alt")
}
if (event.modifiers & Qt.ControlModifier) {
keyNames.push("Ctrl")
}
if (event.modifiers & Qt.ShiftModifier) {
keyNames.push("Shift")
}
var keyName = d.keyToString(event.key,false)
if(keyName!==""){
keyNames.push(keyName)
content_dialog.keysModel = keyNames
}
event.accepted = true
}
Keys.onTabPressed:
(event)=>{
event.accepted = true
}
Row{
spacing: 5
anchors.centerIn: parent
Repeater{
model: content_dialog.keysModel
delegate: ItemKey{
text: modelData
}
}
}
}
}
}
onClicked: {
content_dialog.open()
}
}

View File

@ -16,14 +16,14 @@ Button {
if(checked){ if(checked){
return FluTheme.dark ? Qt.darker(normalColor,1.1) : Qt.lighter(normalColor,1.1) return FluTheme.dark ? Qt.darker(normalColor,1.1) : Qt.lighter(normalColor,1.1)
}else{ }else{
return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(246/255,246/255,246/255,1)
} }
} }
property color disableColor: { property color disableColor: {
if(checked){ if(checked){
return FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1) return FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1)
}else{ }else{
return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(244/255,244/255,244/255,1)
} }
} }
property var clickListener : function(){ property var clickListener : function(){
@ -37,6 +37,7 @@ Button {
focusPolicy:Qt.TabFocus focusPolicy:Qt.TabFocus
id: control id: control
enabled: !disabled enabled: !disabled
verticalPadding: 0
horizontalPadding:12 horizontalPadding:12
onClicked: clickListener() onClicked: clickListener()
onCheckableChanged: { onCheckableChanged: {

View File

@ -3,10 +3,10 @@ import QtQuick.Window 2.15
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15 import QtQuick.Layouts 1.15
import FluentUI 1.0 import FluentUI 1.0
import org.wangwenx190.FramelessHelper 1.0
Window { Window {
default property alias content: container.data default property alias content: layout_content.data
property string windowIcon: FluApp.windowIcon
property bool closeDestory: true property bool closeDestory: true
property int launchMode: FluWindowType.Standard property int launchMode: FluWindowType.Standard
property var argument:({}) property var argument:({})
@ -16,13 +16,13 @@ Window {
property bool fitsAppBarWindows: false property bool fitsAppBarWindows: false
property Item appBar: FluAppBar { property Item appBar: FluAppBar {
title: window.title title: window.title
width: window.width
height: 30 height: 30
showDark: window.showDark showDark: window.showDark
showClose: window.showClose showClose: window.showClose
showMinimize: window.showMinimize showMinimize: window.showMinimize
showMaximize: window.showMaximize showMaximize: window.showMaximize
showStayTop: window.showStayTop showStayTop: window.showStayTop
icon: window.windowIcon
} }
property color backgroundColor: { property color backgroundColor: {
if(active){ if(active){
@ -38,8 +38,10 @@ Window {
property bool showMinimize: true property bool showMinimize: true
property bool showMaximize: true property bool showMaximize: true
property bool showStayTop: true property bool showStayTop: true
property bool useSystemAppBar
property bool autoMaximize: false property bool autoMaximize: false
property bool useSystemAppBar
property color resizeBorderColor: FluTheme.dark ? Qt.rgba(80/255,80/255,80/255,1) : Qt.rgba(210/255,210/255,210/255,1)
property int resizeBorderWidth: 1
property var closeListener: function(event){ property var closeListener: function(event){
if(closeDestory){ if(closeDestory){
destoryOnClose() destoryOnClose()
@ -51,28 +53,25 @@ Window {
signal initArgument(var argument) signal initArgument(var argument)
signal firstVisible() signal firstVisible()
id:window id:window
maximumWidth: useSystemAppBar&&fixSize ? width : 16777215 maximumWidth: fixSize ? width : 16777215
maximumHeight: useSystemAppBar&&fixSize ? height : 16777215 maximumHeight: fixSize ? height : 16777215
minimumWidth: useSystemAppBar&&fixSize ? width : 0 minimumWidth: fixSize ? width : 0
minimumHeight: useSystemAppBar&&fixSize ? height : 0 minimumHeight: fixSize ? height : 0
color:"transparent" color:"transparent"
onStayTopChanged: {
d.changedStayTop()
}
Component.onCompleted: { Component.onCompleted: {
useSystemAppBar = FluApp.useSystemAppBar useSystemAppBar = FluApp.useSystemAppBar
if(!useSystemAppBar){
loader_frameless.sourceComponent = com_frameless
}
lifecycle.onCompleted(window) lifecycle.onCompleted(window)
initArgument(argument) initArgument(argument)
d.changedStayTop() moveWindowToDesktopCenter()
if(useSystemAppBar){
window.moveWindowToDesktopCenter()
if(window.autoMaximize){ if(window.autoMaximize){
window.showMaximized() window.showMaximized()
}else{ }else{
window.show() window.show()
} }
} }
}
Component.onDestruction: { Component.onDestruction: {
lifecycle.onDestruction() lifecycle.onDestruction()
} }
@ -86,73 +85,26 @@ Window {
QtObject{ QtObject{
id:d id:d
property bool isFirstVisible: true property bool isFirstVisible: true
function changedStayTop(){
function toggleStayTop(){
if(window.stayTop){
window.flags = window.flags | Qt.WindowStaysOnTopHint
}else{
window.flags = window.flags &~ Qt.WindowStaysOnTopHint
}
}
if(window.visibility === Window.Maximized){
window.visibility = Window.Windowed
toggleStayTop()
window.visibility = Window.Maximized
}else{
toggleStayTop()
}
}
} }
Connections{ Connections{
target: window target: window
function onClosing(event){closeListener(event)} function onClosing(event){closeListener(event)}
} }
Component{
id:com_frameless
FluFramelessHelper{}
}
Component{ Component{
id:com_background id:com_background
Rectangle{ Rectangle{
color: window.backgroundColor color: window.backgroundColor
} }
} }
FluLoader{
anchors.fill: parent
sourceComponent: background
}
FluLoader{
id:loader_app_bar
anchors {
top: parent.top
left: parent.left
right: parent.right
}
sourceComponent: window.useSystemAppBar ? undefined : com_app_bar
}
Component{ Component{
id:com_app_bar id:com_app_bar
Item{ Item{
data: window.appBar data: window.appBar
height: {
if(FluApp.useSystemAppBar){
return 0
} }
return window.fitsAppBarWindows ? 0 : childrenRect.height
}
}
}
Item{
id:container
anchors{
top: loader_app_bar.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
clip: true
}
FluLoader{
property string loadingText: "加载中..."
property bool cancel: false
id:loader_loading
anchors.fill: container
} }
Component{ Component{
id:com_loading id:com_loading
@ -216,64 +168,94 @@ Window {
} }
} }
} }
FluLoader{
id:loader_frameless
}
Item{
id:layout_container
property int offsetX: {
if(window.visibility === Window.Maximized){
var dx = window.x-Screen.virtualX
if(dx<0){
return Math.abs(dx)
}
}
return 0
}
property int offsetY: {
if(window.visibility === Window.Maximized){
var dy = window.y-Screen.virtualY
if(dy<0){
return Math.abs(dy)
}
}
return 0
}
anchors{
fill:parent
leftMargin: offsetX
rightMargin: offsetX
topMargin: offsetY
bottomMargin: offsetY
}
onWidthChanged: {
window.appBar.width = width
}
FluLoader{
anchors.fill: parent
sourceComponent: background
}
FluLoader{
id:loader_app_bar
anchors {
top: parent.top
left: parent.left
right: parent.right
}
height: {
if(window.useSystemAppBar){
return 0
}
return window.fitsAppBarWindows ? 0 : window.appBar.height
}
sourceComponent: window.useSystemAppBar ? undefined : com_app_bar
}
Item{
id:layout_content
anchors{
top: loader_app_bar.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
clip: true
}
FluLoader{
property string loadingText: "加载中..."
property bool cancel: false
id:loader_loading
anchors.fill: layout_content
}
FluInfoBar{ FluInfoBar{
id:infoBar id:infoBar
root: window root: window
} }
Connections{
target: FluTheme
function onDarkChanged(){
if (FluTheme.dark)
FramelessUtils.systemTheme = FramelessHelperConstants.Dark
else
FramelessUtils.systemTheme = FramelessHelperConstants.Light
}
}
FramelessHelper{
id:framless_helper
onReady: {
flags = flags | Qt.Window | Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint | Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint
if(appBar){
var appbar = window.appBar
window.moveWindowToDesktopCenter()
setWindowFixedSize(fixSize)
if (blurBehindWindowEnabled)
window.background = undefined
}
if(window.autoMaximize){
window.showMaximized()
}else{
window.show()
}
}
}
WindowLifecycle{ WindowLifecycle{
id:lifecycle id:lifecycle
} }
FluLoader{
id:loader_window_border
anchors.fill: parent
z:999
sourceComponent: window.useSystemAppBar ? undefined : com_window_border
}
Component{
id:com_window_border
Item{
WindowBorder{
anchors.fill: parent
visible: !FluTools.isLinux()
}
Rectangle{ Rectangle{
anchors.fill: parent anchors.fill: parent
color: Qt.rgba(0,0,0,0) color:"transparent"
border.width: 1 border.width: window.resizeBorderWidth
visible: FluTools.isLinux() border.color: window.resizeBorderColor
border.color: { visible: {
if(window.active){ if(window.useSystemAppBar){
return Qt.rgba(51/255,51/255,51/255,1) return false
} }
return Qt.rgba(153/255,153/255,153/255,1) if(window.visibility == Window.Maximized || window.visibility == Window.FullScreen){
return false
} }
return true
} }
} }
} }
@ -304,15 +286,17 @@ Window {
return lifecycle.createRegister(window,path) return lifecycle.createRegister(window,path)
} }
function moveWindowToDesktopCenter(){ function moveWindowToDesktopCenter(){
window.x = (Screen.desktopAvailableWidth - window.width)/2 window.setGeometry((Screen.width-window.width)/2+Screen.virtualX,(Screen.height-window.height)/2+Screen.virtualY,window.width,window.height)
window.y = (Screen.desktopAvailableHeight - window.height)/2
} }
function onResult(data){ function onResult(data){
if(_pageRegister){ if(_pageRegister){
_pageRegister.onResult(data) _pageRegister.onResult(data)
} }
} }
function containerItem(){ function layoutContainer(){
return container return layout_container
}
function layoutContent(){
return layout_content
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,7 +1,7 @@
/*! /*!
* Chart.js v2.9.3 * Chart.js v2.9.4
* https://www.chartjs.org * https://www.chartjs.org
* (c) 2019 Chart.js Contributors * (c) 2020 Chart.js Contributors
* Released under the MIT License * Released under the MIT License
*/ */
@ -28,7 +28,7 @@ typeof define === 'function' && define.amd ? define(factory) :
function Chart (item, config) { 'use strict'; function Chart (item, config) { 'use strict';
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof _window !== 'undefined' ? _window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function commonjsRequire () { function commonjsRequire () {
throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs'); throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
@ -1638,6 +1638,10 @@ function keyword(rgb) {
return reverseNames[rgb.slice(0, 3)]; return reverseNames[rgb.slice(0, 3)];
} }
/* MIT license */
var Color = function (obj) { var Color = function (obj) {
if (obj instanceof Color) { if (obj instanceof Color) {
return obj; return obj;
@ -2114,12 +2118,17 @@ Color.prototype.setChannel = function (space, index, val) {
return this; return this;
}; };
if (typeof window !== 'undefined') { if (typeof _window !== 'undefined') {
// window.Color = Color; console.debug(_window)
_window.Color = Color;
} }
var chartjsColor = Color; var chartjsColor = Color;
function isValidKey(key) {
return ['__proto__', 'prototype', 'constructor'].indexOf(key) === -1;
}
/** /**
* @namespace Chart.helpers * @namespace Chart.helpers
*/ */
@ -2295,7 +2304,7 @@ var helpers = {
} }
if (helpers.isObject(source)) { if (helpers.isObject(source)) {
var target = {}; var target = Object.create(source);
var keys = Object.keys(source); var keys = Object.keys(source);
var klen = keys.length; var klen = keys.length;
var k = 0; var k = 0;
@ -2316,6 +2325,12 @@ var helpers = {
* @private * @private
*/ */
_merger: function(key, target, source, options) { _merger: function(key, target, source, options) {
if (!isValidKey(key)) {
// We want to ensure we do not copy prototypes over
// as this can pollute global namespaces
return;
}
var tval = target[key]; var tval = target[key];
var sval = source[key]; var sval = source[key];
@ -2331,6 +2346,12 @@ var helpers = {
* @private * @private
*/ */
_mergerIf: function(key, target, source) { _mergerIf: function(key, target, source) {
if (!isValidKey(key)) {
// We want to ensure we do not copy prototypes over
// as this can pollute global namespaces
return;
}
var tval = target[key]; var tval = target[key];
var sval = source[key]; var sval = source[key];
@ -3832,7 +3853,7 @@ helpers$1.extend(DatasetController.prototype, {
*/ */
_configure: function() { _configure: function() {
var me = this; var me = this;
me._config = helpers$1.merge({}, [ me._config = helpers$1.merge(Object.create(null), [
me.chart.options.datasets[me._type], me.chart.options.datasets[me._type],
me.getDataset(), me.getDataset(),
], { ], {
@ -6142,9 +6163,9 @@ var controller_line = core_datasetController.extend({
}; };
model.backgroundColor = valueOrDefault$6(options.hoverBackgroundColor, getHoverColor(options.backgroundColor)); model.backgroundColor = valueOrDefault$6(options.hoverBackgroundColor, getHoverColor(options.backgroundColor));
model.borderColor = "rgba(255,0,0,1.)";//valueOrDefault$6(options.hoverBorderColor, getHoverColor(options.borderColor)); model.borderColor = valueOrDefault$6(options.hoverBorderColor, getHoverColor(options.borderColor));
model.borderWidth = 1;//valueOrDefault$6(options.hoverBorderWidth, options.borderWidth); model.borderWidth = valueOrDefault$6(options.hoverBorderWidth, options.borderWidth);
model.radius = 2;//valueOrDefault$6(options.hoverRadius, options.radius); model.radius = valueOrDefault$6(options.hoverRadius, options.radius);
}, },
}); });
@ -7105,7 +7126,8 @@ function updateDims(chartArea, params, layout) {
chartArea.h = newHeight; chartArea.h = newHeight;
// return true if chart area changed in layout's direction // return true if chart area changed in layout's direction
return layout.horizontal ? newWidth !== chartArea.w : newHeight !== chartArea.h; var sizes = layout.horizontal ? [newWidth, chartArea.w] : [newHeight, chartArea.h];
return sizes[0] !== sizes[1] && (!isNaN(sizes[0]) || !isNaN(sizes[1]));
} }
} }
@ -7526,7 +7548,7 @@ var supportsEventListenerOptions = (function() {
supports = true; supports = true;
} }
}); });
window.addEventListener('e', null, options); _window.addEventListener('e', null, options);
} catch (e) { } catch (e) {
// continue regardless of error // continue regardless of error
} }
@ -7571,7 +7593,7 @@ function throttled(fn, thisArg) {
if (!ticking) { if (!ticking) {
ticking = true; ticking = true;
helpers$1.requestAnimFrame.call(window, function() { helpers$1.requestAnimFrame.call(_window, function() {
ticking = false; ticking = false;
fn.apply(thisArg, args); fn.apply(thisArg, args);
}); });
@ -7738,7 +7760,7 @@ var platform_dom$2 = {
* Currently used by platform.js to select the proper implementation. * Currently used by platform.js to select the proper implementation.
* @private * @private
*/ */
_enabled: typeof window !== 'undefined' && typeof document !== 'undefined', _enabled: typeof _window !== 'undefined' && typeof document !== 'undefined',
/** /**
* Initializes resources that depend on platform options. * Initializes resources that depend on platform options.
@ -8117,7 +8139,7 @@ var core_scaleService = {
}, },
getScaleDefaults: function(type) { getScaleDefaults: function(type) {
// Return the scale defaults merged with the global settings so that we always use the latest ones // Return the scale defaults merged with the global settings so that we always use the latest ones
return this.defaults.hasOwnProperty(type) ? helpers$1.merge({}, [core_defaults.scale, this.defaults[type]]) : {}; return this.defaults.hasOwnProperty(type) ? helpers$1.merge(Object.create(null), [core_defaults.scale, this.defaults[type]]) : {};
}, },
updateScaleDefaults: function(type, additions) { updateScaleDefaults: function(type, additions) {
var me = this; var me = this;
@ -9192,7 +9214,7 @@ core_defaults._set('global', {
* returns a deep copy of the result, thus doesn't alter inputs. * returns a deep copy of the result, thus doesn't alter inputs.
*/ */
function mergeScaleConfig(/* config objects ... */) { function mergeScaleConfig(/* config objects ... */) {
return helpers$1.merge({}, [].slice.call(arguments), { return helpers$1.merge(Object.create(null), [].slice.call(arguments), {
merger: function(key, target, source, options) { merger: function(key, target, source, options) {
if (key === 'xAxes' || key === 'yAxes') { if (key === 'xAxes' || key === 'yAxes') {
var slen = source[key].length; var slen = source[key].length;
@ -9232,9 +9254,9 @@ function mergeScaleConfig(/* config objects ... */) {
* a deep copy of the result, thus doesn't alter inputs. * a deep copy of the result, thus doesn't alter inputs.
*/ */
function mergeConfig(/* config objects ... */) { function mergeConfig(/* config objects ... */) {
return helpers$1.merge({}, [].slice.call(arguments), { return helpers$1.merge(Object.create(null), [].slice.call(arguments), {
merger: function(key, target, source, options) { merger: function(key, target, source, options) {
var tval = target[key] || {}; var tval = target[key] || Object.create(null);
var sval = source[key]; var sval = source[key];
if (key === 'scales') { if (key === 'scales') {
@ -9251,7 +9273,7 @@ function mergeConfig(/* config objects ... */) {
} }
function initConfig(config) { function initConfig(config) {
config = config || {}; config = config || Object.create(null);
// Do NOT use mergeConfig for the data object because this method merges arrays // Do NOT use mergeConfig for the data object because this method merges arrays
// and so would change references to labels and datasets, preventing data updates. // and so would change references to labels and datasets, preventing data updates.
@ -9778,7 +9800,6 @@ helpers$1.extend(Chart.prototype, /** @lends Chart */ {
} }
var animationOptions = me.options.animation; var animationOptions = me.options.animation;
var duration = valueOrDefault$9(config.duration, animationOptions && animationOptions.duration); var duration = valueOrDefault$9(config.duration, animationOptions && animationOptions.duration);
var lazy = config.lazy; var lazy = config.lazy;
@ -9915,7 +9936,6 @@ helpers$1.extend(Chart.prototype, /** @lends Chart */ {
} }
metasets = me._getSortedVisibleDatasetMetas(); metasets = me._getSortedVisibleDatasetMetas();
for (i = metasets.length - 1; i >= 0; --i) { for (i = metasets.length - 1; i >= 0; --i) {
me.drawDataset(metasets[i], easingValue); me.drawDataset(metasets[i], easingValue);
} }
@ -10643,18 +10663,18 @@ var core_helpers = function() {
}; };
// Request animation polyfill - https://www.paulirish.com/2011/requestanimationframe-for-smart-animating/ // Request animation polyfill - https://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
helpers$1.requestAnimFrame = (function() { helpers$1.requestAnimFrame = (function() {
if (typeof window === 'undefined') { if (typeof _window === 'undefined') {
return function(callback) { return function(callback) {
callback(); callback();
}; };
} }
return window.requestAnimationFrame || return _window.requestAnimationFrame ||
window.webkitRequestAnimationFrame || _window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame || _window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame || _window.oRequestAnimationFrame ||
window.msRequestAnimationFrame || _window.msRequestAnimationFrame ||
function(callback) { function(callback) {
return window.setTimeout(callback, 1000 / 60); return _window.setTimeout(callback, 1000 / 60);
}; };
}()); }());
// -- DOM methods // -- DOM methods
@ -10785,7 +10805,7 @@ var core_helpers = function() {
document.defaultView.getComputedStyle(el, null).getPropertyValue(property); document.defaultView.getComputedStyle(el, null).getPropertyValue(property);
}; };
helpers$1.retinaScale = function(chart, forceRatio) { helpers$1.retinaScale = function(chart, forceRatio) {
var pixelRatio = chart.currentDevicePixelRatio = forceRatio || (typeof window !== 'undefined' && window.devicePixelRatio) || 1; var pixelRatio = chart.currentDevicePixelRatio = forceRatio || (typeof _window !== 'undefined' && _window.devicePixelRatio) || 1;
if (pixelRatio === 1) { if (pixelRatio === 1) {
return; return;
} }
@ -11215,6 +11235,8 @@ function computeLabelSizes(ctx, tickFonts, ticks, caches) {
var widths = []; var widths = [];
var heights = []; var heights = [];
var offsets = []; var offsets = [];
var widestLabelSize = 0;
var highestLabelSize = 0;
var i, j, jlen, label, tickFont, fontString, cache, lineHeight, width, height, nestedLabel, widest, highest; var i, j, jlen, label, tickFont, fontString, cache, lineHeight, width, height, nestedLabel, widest, highest;
for (i = 0; i < length; ++i) { for (i = 0; i < length; ++i) {
@ -11242,11 +11264,13 @@ function computeLabelSizes(ctx, tickFonts, ticks, caches) {
widths.push(width); widths.push(width);
heights.push(height); heights.push(height);
offsets.push(lineHeight / 2); offsets.push(lineHeight / 2);
widestLabelSize = Math.max(width, widestLabelSize);
highestLabelSize = Math.max(height, highestLabelSize);
} }
garbageCollect(caches, length); garbageCollect(caches, length);
widest = widths.indexOf(Math.max.apply(null, widths)); widest = widths.indexOf(widestLabelSize);
highest = heights.indexOf(Math.max.apply(null, heights)); highest = heights.indexOf(highestLabelSize);
function valueAt(idx) { function valueAt(idx) {
return { return {
@ -20668,8 +20692,9 @@ core_controller.platform.initialize();
var src = core_controller; var src = core_controller;
if (window !== 'undefined') { if (typeof _window !== 'undefined') {
// window.Chart = core_controller; console.debug(_window)
_window.Chart = core_controller;
} }
// DEPRECATIONS // DEPRECATIONS

View File

@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only. // It is used for QML tooling purposes only.
// //
// This file was auto-generated by: // This file was auto-generated by:
// 'qmlplugindump -nonrelocatable FluentUI 1.0 D:/QtProjects/build-FluentUI-Desktop_Qt_5_15_2_MSVC2019_64bit-Release/src' // 'qmlplugindump -nonrelocatable FluentUI 1.0 D:\QtProjects\build-FluentUI-Desktop_Qt_5_15_2_MSVC2019_64bit-Release\src'
Module { Module {
dependencies: ["QtQuick 2.0"] dependencies: ["QtQuick 2.0"]
@ -75,6 +75,12 @@ Module {
Parameter { name: "data"; type: "QVariantMap" } Parameter { name: "data"; type: "QVariantMap" }
} }
} }
Component {
name: "FluFramelessHelper"
prototype: "QObject"
exports: ["FluentUI/FluFramelessHelper 1.0"]
exportMetaObjectRevisions: [0]
}
Component { Component {
name: "FluNavigationViewType" name: "FluNavigationViewType"
exports: ["FluentUI/FluNavigationViewType 1.0"] exports: ["FluentUI/FluNavigationViewType 1.0"]
@ -1866,6 +1872,11 @@ Module {
type: "NetworkParams*" type: "NetworkParams*"
Parameter { name: "target"; type: "QObject"; isPointer: true } Parameter { name: "target"; type: "QObject"; isPointer: true }
} }
Method {
name: "openLog"
type: "NetworkParams*"
Parameter { name: "val"; type: "QVariant" }
}
Method { Method {
name: "go" name: "go"
Parameter { name: "result"; type: "NetworkCallable"; isPointer: true } Parameter { name: "result"; type: "NetworkCallable"; isPointer: true }
@ -2538,17 +2549,12 @@ Module {
exportMetaObjectRevisions: [0] exportMetaObjectRevisions: [0]
isComposite: true isComposite: true
defaultProperty: "data" defaultProperty: "data"
Property { name: "window"; type: "QVariant" }
Property { name: "jsChart"; type: "QVariant" }
Property { name: "chartType"; type: "string" } Property { name: "chartType"; type: "string" }
Property { name: "chartData"; type: "QVariant" } Property { name: "chartData"; type: "QVariant" }
Property { name: "chartOptions"; type: "QVariant" } Property { name: "chartOptions"; type: "QVariant" }
Property { name: "chartAnimationProgress"; type: "double" } Property { name: "chartAnimationProgress"; type: "double" }
Property { name: "animationEasingType"; type: "int" } Property { name: "animationEasingType"; type: "int" }
Property { name: "animationDuration"; type: "double" } Property { name: "animationDuration"; type: "double" }
Property { name: "memorizedContext"; type: "QVariant" }
Property { name: "memorizedData"; type: "QVariant" }
Property { name: "memorizedOptions"; type: "QVariant" }
Property { name: "animationRunning"; type: "bool" } Property { name: "animationRunning"; type: "bool" }
Signal { name: "animationFinished" } Signal { name: "animationFinished" }
Method { name: "animateToNewData"; type: "QVariant" } Method { name: "animateToNewData"; type: "QVariant" }
@ -2649,9 +2655,13 @@ Module {
Property { name: "neutralText"; type: "string" } Property { name: "neutralText"; type: "string" }
Property { name: "negativeText"; type: "string" } Property { name: "negativeText"; type: "string" }
Property { name: "positiveText"; type: "string" } Property { name: "positiveText"; type: "string" }
Property { name: "messageTextFormart"; type: "int" }
Property { name: "delayTime"; type: "int" } Property { name: "delayTime"; type: "int" }
Property { name: "buttonFlags"; type: "int" } Property { name: "buttonFlags"; type: "int" }
Property { name: "messageTextFormart"; type: "int" } Property { name: "contentDelegate"; type: "QVariant" }
Property { name: "onNeutralClickListener"; type: "QVariant" }
Property { name: "onNegativeClickListener"; type: "QVariant" }
Property { name: "onPositiveClickListener"; type: "QVariant" }
Signal { name: "neutralClicked" } Signal { name: "neutralClicked" }
Signal { name: "negativeClicked" } Signal { name: "negativeClicked" }
Signal { name: "positiveClicked" } Signal { name: "positiveClicked" }
@ -3003,15 +3013,15 @@ Module {
defaultProperty: "data" defaultProperty: "data"
Property { name: "logo"; type: "QUrl" } Property { name: "logo"; type: "QUrl" }
Property { name: "title"; type: "string" } Property { name: "title"; type: "string" }
Property { name: "items"; type: "FluObject_QMLTYPE_124"; isPointer: true } Property { name: "items"; type: "FluObject_QMLTYPE_125"; isPointer: true }
Property { name: "footerItems"; type: "FluObject_QMLTYPE_124"; isPointer: true } Property { name: "footerItems"; type: "FluObject_QMLTYPE_125"; isPointer: true }
Property { name: "displayMode"; type: "int" } Property { name: "displayMode"; type: "int" }
Property { name: "autoSuggestBox"; type: "QQmlComponent"; isPointer: true } Property { name: "autoSuggestBox"; type: "QQmlComponent"; isPointer: true }
Property { name: "actionItem"; type: "QQmlComponent"; isPointer: true } Property { name: "actionItem"; type: "QQmlComponent"; isPointer: true }
Property { name: "topPadding"; type: "int" } Property { name: "topPadding"; type: "int" }
Property { name: "pageMode"; type: "int" } Property { name: "pageMode"; type: "int" }
Property { name: "navItemRightMenu"; type: "FluMenu_QMLTYPE_39"; isPointer: true } Property { name: "navItemRightMenu"; type: "FluMenu_QMLTYPE_34"; isPointer: true }
Property { name: "navItemExpanderRightMenu"; type: "FluMenu_QMLTYPE_39"; isPointer: true } Property { name: "navItemExpanderRightMenu"; type: "FluMenu_QMLTYPE_34"; isPointer: true }
Property { name: "navCompactWidth"; type: "int" } Property { name: "navCompactWidth"; type: "int" }
Property { name: "navTopMargin"; type: "int" } Property { name: "navTopMargin"; type: "int" }
Property { name: "cellHeight"; type: "int" } Property { name: "cellHeight"; type: "int" }
@ -3758,6 +3768,91 @@ Module {
Method { name: "allExpand"; type: "QVariant" } Method { name: "allExpand"; type: "QVariant" }
Method { name: "allCollapse"; type: "QVariant" } Method { name: "allCollapse"; type: "QVariant" }
} }
Component {
prototype: "QQuickWindowQmlImpl"
name: "FluentUI/FluWindow 1.0"
exports: ["FluentUI/FluWindow 1.0"]
exportMetaObjectRevisions: [0]
isComposite: true
defaultProperty: "content"
Property { name: "windowIcon"; type: "string" }
Property { name: "closeDestory"; type: "bool" }
Property { name: "launchMode"; type: "int" }
Property { name: "argument"; type: "QVariant" }
Property { name: "background"; type: "QVariant" }
Property { name: "fixSize"; type: "bool" }
Property { name: "loadingItem"; type: "QQmlComponent"; isPointer: true }
Property { name: "fitsAppBarWindows"; type: "bool" }
Property { name: "appBar"; type: "QQuickItem"; isPointer: true }
Property { name: "backgroundColor"; type: "QColor" }
Property { name: "stayTop"; type: "bool" }
Property { name: "_pageRegister"; type: "QVariant" }
Property { name: "_route"; type: "string" }
Property { name: "showDark"; type: "bool" }
Property { name: "showClose"; type: "bool" }
Property { name: "showMinimize"; type: "bool" }
Property { name: "showMaximize"; type: "bool" }
Property { name: "showStayTop"; type: "bool" }
Property { name: "autoMaximize"; type: "bool" }
Property { name: "useSystemAppBar"; type: "bool" }
Property { name: "resizeBorderColor"; type: "QColor" }
Property { name: "resizeBorderWidth"; type: "int" }
Property { name: "closeListener"; type: "QVariant" }
Property { name: "content"; type: "QObject"; isList: true; isReadonly: true }
Signal {
name: "initArgument"
Parameter { name: "argument"; type: "QVariant" }
}
Signal { name: "firstVisible" }
Method { name: "destoryOnClose"; type: "QVariant" }
Method {
name: "showLoading"
type: "QVariant"
Parameter { name: "text"; type: "QVariant" }
Parameter { name: "cancel"; type: "QVariant" }
}
Method { name: "hideLoading"; type: "QVariant" }
Method {
name: "showSuccess"
type: "QVariant"
Parameter { name: "text"; type: "QVariant" }
Parameter { name: "duration"; type: "QVariant" }
Parameter { name: "moremsg"; type: "QVariant" }
}
Method {
name: "showInfo"
type: "QVariant"
Parameter { name: "text"; type: "QVariant" }
Parameter { name: "duration"; type: "QVariant" }
Parameter { name: "moremsg"; type: "QVariant" }
}
Method {
name: "showWarning"
type: "QVariant"
Parameter { name: "text"; type: "QVariant" }
Parameter { name: "duration"; type: "QVariant" }
Parameter { name: "moremsg"; type: "QVariant" }
}
Method {
name: "showError"
type: "QVariant"
Parameter { name: "text"; type: "QVariant" }
Parameter { name: "duration"; type: "QVariant" }
Parameter { name: "moremsg"; type: "QVariant" }
}
Method {
name: "registerForWindowResult"
type: "QVariant"
Parameter { name: "path"; type: "QVariant" }
}
Method { name: "moveWindowToDesktopCenter"; type: "QVariant" }
Method {
name: "onResult"
type: "QVariant"
Parameter { name: "data"; type: "QVariant" }
}
Method { name: "containerItem"; type: "QVariant" }
}
Component { Component {
prototype: "QQuickRow" prototype: "QQuickRow"
name: "FluentUI/NumberBox 1.0" name: "FluentUI/NumberBox 1.0"

View File

@ -96,4 +96,5 @@ FluProgressButton 1.0 Controls/FluProgressButton.qml
FluLoadingButton 1.0 Controls/FluLoadingButton.qml FluLoadingButton 1.0 Controls/FluLoadingButton.qml
FluClip 1.0 Controls/FluClip.qml FluClip 1.0 Controls/FluClip.qml
FluLoader 1.0 Controls/FluLoader.qml FluLoader 1.0 Controls/FluLoader.qml
FluShortcutPicker 1.0 Controls/FluShortcutPicker.qml
plugin fluentuiplugin plugin fluentuiplugin

View File

@ -96,5 +96,16 @@
<file>FluentUI/Controls/FluLoadingButton.qml</file> <file>FluentUI/Controls/FluLoadingButton.qml</file>
<file>FluentUI/Controls/FluClip.qml</file> <file>FluentUI/Controls/FluClip.qml</file>
<file>FluentUI/Controls/FluLoader.qml</file> <file>FluentUI/Controls/FluLoader.qml</file>
<file>FluentUI/Controls/FluShortcutPicker.qml</file>
<file>FluentUI/Image/btn_close_hovered.png</file>
<file>FluentUI/Image/btn_close_normal.png</file>
<file>FluentUI/Image/btn_close_pushed.png</file>
<file>FluentUI/Image/btn_max_hovered.png</file>
<file>FluentUI/Image/btn_max_normal.png</file>
<file>FluentUI/Image/btn_max_pushed.png</file>
<file>FluentUI/Image/btn_min_hovered.png</file>
<file>FluentUI/Image/btn_min_normal.png</file>
<file>FluentUI/Image/btn_min_pushed.png</file>
<file>FluentUI/Controls/FluImageButton.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -34,11 +34,18 @@ Rectangle{
property bool isMac: FluTools.isMacos() property bool isMac: FluTools.isMacos()
property color borerlessColor : FluTheme.primaryColor property color borerlessColor : FluTheme.primaryColor
property var maxClickListener : function(){ property var maxClickListener : function(){
if(FluTools.isMacos()){
if (d.win.visibility === Window.FullScreen)
d.win.visibility = Window.Windowed
else
d.win.visibility = Window.FullScreen
}else{
if (d.win.visibility === Window.Maximized) if (d.win.visibility === Window.Maximized)
d.win.visibility = Window.Windowed d.win.visibility = Window.Windowed
else else
d.win.visibility = Window.Maximized d.win.visibility = Window.Maximized
} }
}
property var minClickListener: function(){ property var minClickListener: function(){
d.win.visibility = Window.Minimized d.win.visibility = Window.Minimized
} }
@ -74,14 +81,16 @@ Rectangle{
property bool isRestore: win && Window.Maximized === win.visibility property bool isRestore: win && Window.Maximized === win.visibility
property bool resizable: win && !(win.height === win.maximumHeight && win.height === win.minimumHeight && win.width === win.maximumWidth && win.width === win.minimumWidth) property bool resizable: win && !(win.height === win.maximumHeight && win.height === win.minimumHeight && win.width === win.maximumWidth && win.width === win.minimumWidth)
} }
TapHandler { MouseArea{
onTapped: if (tapCount === 2 && d.resizable) btn_maximize.clicked() anchors.fill: parent
gesturePolicy: TapHandler.DragThreshold onPositionChanged: {
d.win.startSystemMove()
}
onDoubleClicked: {
if(d.resizable){
btn_maximize.clicked()
}
} }
DragHandler {
target: null
grabPermissions: TapHandler.CanTakeOverFromAnything
onActiveChanged: if (active) { d.win.startSystemMove(); }
} }
Row{ Row{
anchors{ anchors{
@ -105,6 +114,49 @@ Rectangle{
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
} }
} }
Component{
id:com_mac_buttons
RowLayout{
FluImageButton{
Layout.preferredHeight: 12
Layout.preferredWidth: 12
normalImage: "../Image/btn_close_normal.png"
hoveredImage: "../Image/btn_close_hovered.png"
pushedImage: "../Image/btn_close_pushed.png"
visible: showClose
onClicked: closeClickListener()
}
FluImageButton{
Layout.preferredHeight: 12
Layout.preferredWidth: 12
normalImage: "../Image/btn_min_normal.png"
hoveredImage: "../Image/btn_min_hovered.png"
pushedImage: "../Image/btn_min_pushed.png"
onClicked: minClickListener()
visible: showMinimize
}
FluImageButton{
Layout.preferredHeight: 12
Layout.preferredWidth: 12
normalImage: "../Image/btn_max_normal.png"
hoveredImage: "../Image/btn_max_hovered.png"
pushedImage: "../Image/btn_max_pushed.png"
onClicked: maxClickListener()
visible: d.resizable && showMaximize
}
}
}
FluLoader{
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 10
}
sourceComponent: isMac ? com_mac_buttons : undefined
}
RowLayout{ RowLayout{
anchors.right: parent.right anchors.right: parent.right
height: control.height height: control.height

View File

@ -7,8 +7,8 @@ Button {
property bool disabled: false property bool disabled: false
property string contentDescription: "" property string contentDescription: ""
property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1) property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1)
property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(246/255,246/255,246/255,1)
property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(244/255,244/255,244/255,1)
property color textColor: { property color textColor: {
if(FluTheme.dark){ if(FluTheme.dark){
if(!enabled){ if(!enabled){
@ -34,6 +34,7 @@ Button {
Accessible.onPressAction: control.clicked() Accessible.onPressAction: control.clicked()
id: control id: control
enabled: !disabled enabled: !disabled
verticalPadding: 0
horizontalPadding:12 horizontalPadding:12
font:FluTextStyle.Body font:FluTextStyle.Body
focusPolicy:Qt.TabFocus focusPolicy:Qt.TabFocus

View File

@ -3,25 +3,27 @@ import "./../JS/Chart.js" as Chart
Canvas { Canvas {
id: control id: control
property var window: Window.window
property var jsChart: undefined
property string chartType property string chartType
property var chartData property var chartData
property var chartOptions property var chartOptions
property double chartAnimationProgress: 0.1 property double chartAnimationProgress: 0.1
property int animationEasingType: Easing.InOutExpo property int animationEasingType: Easing.InOutExpo
property double animationDuration: 0 property double animationDuration: 300
property var memorizedContext
property var memorizedData
property var memorizedOptions
property alias animationRunning: chartAnimator.running property alias animationRunning: chartAnimator.running
signal animationFinished() signal animationFinished()
function animateToNewData() function animateToNewData()
{ {
chartAnimationProgress = 0.1; chartAnimationProgress = 0.1;
jsChart.update(); d.jsChart.update();
chartAnimator.restart(); chartAnimator.restart();
} }
QtObject{
id:d
property var jsChart: undefined
property var memorizedContext
property var memorizedData
property var memorizedOptions
}
MouseArea { MouseArea {
id: event id: event
anchors.fill: control anchors.fill: control
@ -47,17 +49,17 @@ Canvas {
mouseEvent.left = 0; mouseEvent.left = 0;
mouseEvent.top = 0; mouseEvent.top = 0;
mouseEvent.target = control; mouseEvent.target = control;
if(handler) { if(handler) {
handler(mouseEvent); handler(mouseEvent);
} }
control.requestPaint(); control.requestPaint();
} }
onClicked:(mouse)=> { onClicked:
(mouse)=> {
submitEvent(mouse, "click"); submitEvent(mouse, "click");
} }
onPositionChanged:(mouse)=> { onPositionChanged:
(mouse)=> {
submitEvent(mouse, "mousemove"); submitEvent(mouse, "mousemove");
} }
onExited: { onExited: {
@ -66,10 +68,12 @@ Canvas {
onEntered: { onEntered: {
submitEvent(undefined, "mouseenter"); submitEvent(undefined, "mouseenter");
} }
onPressed:(mouse)=> { onPressed:
(mouse)=> {
submitEvent(mouse, "mousedown"); submitEvent(mouse, "mousedown");
} }
onReleased:(mouse)=> { onReleased:
(mouse)=> {
submitEvent(mouse, "mouseup"); submitEvent(mouse, "mouseup");
} }
} }
@ -89,34 +93,25 @@ Canvas {
control.requestPaint(); control.requestPaint();
} }
onPaint: { onPaint: {
if(control.getContext('2d') !== null && memorizedContext !== control.getContext('2d') || memorizedData !== control.chartData || memorizedOptions !== control.chartOptions) { if(control.getContext('2d') !== null && d.memorizedContext !== control.getContext('2d') || d.memorizedData !== control.chartData || d.memorizedOptions !== control.chartOptions) {
var ctx = control.getContext('2d'); var ctx = control.getContext('2d');
d.jsChart = Chart.build(ctx, {type: control.chartType,data: control.chartData,options: control.chartOptions});
jsChart = Chart.build(ctx, { d.memorizedData = control.chartData ;
type: control.chartType, d.memorizedContext = control.getContext('2d');
data: control.chartData, d.memorizedOptions = control.chartOptions;
options: control.chartOptions d.jsChart.bindEvents(function(newHandler) {event.handler = newHandler;});
});
memorizedData = control.chartData ;
memorizedContext = control.getContext('2d');
memorizedOptions = control.chartOptions;
control.jsChart.bindEvents(function(newHandler) {event.handler = newHandler;});
chartAnimator.start(); chartAnimator.start();
} }
d.jsChart.draw(chartAnimationProgress);
jsChart.draw(chartAnimationProgress);
} }
onWidthChanged: { onWidthChanged: {
if(jsChart) { if(d.jsChart) {
jsChart.resize(); d.jsChart.resize();
} }
} }
onHeightChanged: { onHeightChanged: {
if(jsChart) { if(d.jsChart) {
jsChart.resize(); d.jsChart.resize();
} }
} }
} }

View File

@ -5,51 +5,37 @@ import QtQuick.Window
import FluentUI import FluentUI
FluPopup { FluPopup {
id: popup id: control
property string title: "Title" property string title: ""
property string message: "Message" property string message: ""
property string neutralText: "Neutral" property string neutralText: "Neutral"
property string negativeText: "Negative" property string negativeText: "Negative"
property string positiveText: "Positive" property string positiveText: "Positive"
property alias messageTextFormart: text_message.textFormat property int messageTextFormart: Text.AutoText
property int delayTime: 100 property int delayTime: 100
property int buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
property var contentDelegate: Component{
Item{
}
}
property var onNeutralClickListener
property var onNegativeClickListener
property var onPositiveClickListener
signal neutralClicked signal neutralClicked
signal negativeClicked signal negativeClicked
signal positiveClicked signal positiveClicked
property int buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton
focus: true
implicitWidth: 400 implicitWidth: 400
implicitHeight: text_title.height + sroll_message.height + layout_actions.height implicitHeight: layout_content.height
Rectangle { focus: true
id:layout_content Component{
anchors.fill: parent id:com_message
color: 'transparent'
radius:5
FluText{
id:text_title
font: FluTextStyle.TitleLarge
text:title
topPadding: 20
leftPadding: 20
rightPadding: 20
wrapMode: Text.WrapAnywhere
anchors{
top:parent.top
left: parent.left
right: parent.right
}
}
Flickable{ Flickable{
id:sroll_message id:sroll_message
contentHeight: text_message.height
contentWidth: width contentWidth: width
clip: true clip: true
anchors{
top:text_title.bottom
left: parent.left
right: parent.right
}
boundsBehavior:Flickable.StopAtBounds boundsBehavior:Flickable.StopAtBounds
contentHeight: text_message.height width: parent.width
height: Math.min(text_message.height,300) height: Math.min(text_message.height,300)
ScrollBar.vertical: FluScrollBar {} ScrollBar.vertical: FluScrollBar {}
FluText{ FluText{
@ -58,22 +44,47 @@ FluPopup {
wrapMode: Text.WrapAnywhere wrapMode: Text.WrapAnywhere
text:message text:message
width: parent.width width: parent.width
topPadding: 14 topPadding: 4
leftPadding: 20 leftPadding: 20
rightPadding: 20 rightPadding: 20
bottomPadding: 14 bottomPadding: 4
}
} }
} }
Rectangle {
id:layout_content
width: parent.width
height: layout_column.childrenRect.height
color: 'transparent'
radius:5
ColumnLayout{
id:layout_column
width: parent.width
FluText{
id:text_title
font: FluTextStyle.Title
text:title
topPadding: 20
leftPadding: 20
rightPadding: 20
wrapMode: Text.WrapAnywhere
}
FluLoader{
sourceComponent: com_message
Layout.fillWidth: true
Layout.preferredHeight: status===Loader.Ready ? item.height : 0
}
FluLoader{
sourceComponent: control.contentDelegate
Layout.fillWidth: true
Layout.preferredHeight: status===Loader.Ready ? item.height : 0
}
Rectangle{ Rectangle{
id:layout_actions id:layout_actions
height: 68 Layout.fillWidth: true
Layout.preferredHeight: 60
radius: 5 radius: 5
color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1) color: FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
anchors{
top:sroll_message.bottom
left: parent.left
right: parent.right
}
RowLayout{ RowLayout{
anchors anchors
{ {
@ -81,59 +92,65 @@ FluPopup {
margins: spacing margins: spacing
fill: parent fill: parent
} }
spacing: 15 spacing: 10
Item{
Layout.fillWidth: true
Layout.fillHeight: true
visible: control.buttonFlags&FluContentDialogType.NeutralButton
FluButton{ FluButton{
id:neutral_btn id:neutral_btn
text: neutralText
width: parent.width
anchors.centerIn: parent
onClicked: {
if(control.onNeutralClickListener){
control.onNeutralClickListener()
}else{
neutralClicked()
control.close()
}
}
}
}
Item{
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
visible: popup.buttonFlags&FluContentDialogType.NeutralButton visible: control.buttonFlags&FluContentDialogType.NegativeButton
text: neutralText
onClicked: {
popup.close()
timer_delay.targetFlags = FluContentDialogType.NeutralButton
timer_delay.restart()
}
}
FluButton{ FluButton{
id:negative_btn id:negative_btn
Layout.fillWidth: true width: parent.width
Layout.fillHeight: true anchors.centerIn: parent
visible: popup.buttonFlags&FluContentDialogType.NegativeButton
text: negativeText text: negativeText
onClicked: { onClicked: {
popup.close() if(control.onNegativeClickListener){
timer_delay.targetFlags = FluContentDialogType.NegativeButton control.onNegativeClickListener()
timer_delay.restart() }else{
negativeClicked()
control.close()
} }
} }
FluFilledButton{ }
id:positive_btn }
Item{
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
visible: popup.buttonFlags&FluContentDialogType.PositiveButton visible: control.buttonFlags&FluContentDialogType.PositiveButton
FluFilledButton{
id:positive_btn
text: positiveText text: positiveText
width: parent.width
anchors.centerIn: parent
onClicked: { onClicked: {
popup.close() if(control.onPositiveClickListener){
timer_delay.targetFlags = FluContentDialogType.PositiveButton control.onPositiveClickListener()
timer_delay.restart() }else{
}
}
}
}
}
Timer{
property int targetFlags
id:timer_delay
interval: popup.delayTime
onTriggered: {
if(targetFlags === FluContentDialogType.NegativeButton){
negativeClicked()
}
if(targetFlags === FluContentDialogType.NeutralButton){
neutralClicked()
}
if(targetFlags === FluContentDialogType.PositiveButton){
positiveClicked() positiveClicked()
control.close()
}
}
}
}
}
} }
} }
} }

View File

@ -8,8 +8,8 @@ Button {
property bool disabled: false property bool disabled: false
property string contentDescription: "" property string contentDescription: ""
property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1) property color normalColor: FluTheme.dark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(254/255,254/255,254/255,1)
property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) property color hoverColor: FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(246/255,246/255,246/255,1)
property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) property color disableColor: FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(244/255,244/255,244/255,1)
property color textColor: { property color textColor: {
if(FluTheme.dark){ if(FluTheme.dark){
if(!enabled){ if(!enabled){
@ -39,6 +39,7 @@ Button {
rightPadding:35 rightPadding:35
enabled: !disabled enabled: !disabled
focusPolicy:Qt.TabFocus focusPolicy:Qt.TabFocus
verticalPadding: 0
horizontalPadding:12 horizontalPadding:12
background: Rectangle{ background: Rectangle{
implicitWidth: 28 implicitWidth: 28

View File

@ -28,6 +28,7 @@ Button {
enabled: !disabled enabled: !disabled
focusPolicy:Qt.TabFocus focusPolicy:Qt.TabFocus
font:FluTextStyle.Body font:FluTextStyle.Body
verticalPadding: 0
horizontalPadding:12 horizontalPadding:12
background: Rectangle{ background: Rectangle{
implicitWidth: 28 implicitWidth: 28

View File

@ -0,0 +1,18 @@
import QtQuick
import QtQuick.Controls
import FluentUI
Button{
id:control
property string normalImage: ""
property string hoveredImage: ""
property string pushedImage: ""
background: Item{
implicitHeight: 12
implicitWidth: 12
BorderImage {
anchors.fill: parent
source: control.hovered ? (control.pressed ? control.pushedImage : control.hoveredImage ) : control.normalImage
}
}
}

View File

@ -22,14 +22,14 @@ Button {
if(d.checked){ if(d.checked){
return FluTheme.dark ? Qt.darker(normalColor,1.1) : Qt.lighter(normalColor,1.1) return FluTheme.dark ? Qt.darker(normalColor,1.1) : Qt.lighter(normalColor,1.1)
}else{ }else{
return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(246/255,246/255,246/255,1)
} }
} }
property color disableColor: { property color disableColor: {
if(d.checked){ if(d.checked){
return FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1) return FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1)
}else{ }else{
return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(244/255,244/255,244/255,1)
} }
} }
property color pressedColor: FluTheme.dark ? Qt.darker(normalColor,1.2) : Qt.lighter(normalColor,1.2) property color pressedColor: FluTheme.dark ? Qt.darker(normalColor,1.2) : Qt.lighter(normalColor,1.2)
@ -40,6 +40,7 @@ Button {
focusPolicy:Qt.TabFocus focusPolicy:Qt.TabFocus
id: control id: control
enabled: !disabled enabled: !disabled
verticalPadding: 0
horizontalPadding:12 horizontalPadding:12
background: FluClip{ background: FluClip{
implicitWidth: 28 implicitWidth: 28

View File

@ -0,0 +1,231 @@
import QtQuick
import QtQuick.Controls
import FluentUI
FluIconButton {
id:control
property var current : ["Ctrl","Shift","A"]
property string title: "激活快捷键"
property string message: "按下组合键以更改此快捷键"
property string positiveText: "保存"
property string neutralText: "取消"
property string negativeText: "重置"
signal accepted()
QtObject{
id: d
function keyToString(key_code,shift = true)
{
switch(key_code)
{
case Qt.Key_Period: return ".";
case Qt.Key_Greater: return shift ? ">" : ".";
case Qt.Key_Comma: return ",";
case Qt.Key_Less: return shift ? "<" : ",";
case Qt.Key_Slash: return "/";
case Qt.Key_Question: return shift ? "?" : "/";
case Qt.Key_Semicolon: return ";";
case Qt.Key_Colon: return shift ? ":" : ";";
case Qt.Key_Apostrophe: return "'";
case Qt.Key_QuoteDbl: return shift ? "'" : "\"";
case Qt.Key_QuoteLeft: return "`";
case Qt.Key_AsciiTilde: return shift ? "~" : "`";
case Qt.Key_Minus: return "-";
case Qt.Key_Underscore: return shift ? "_" : "-";
case Qt.Key_Equal: return "=";
case Qt.Key_Plus: return shift ? "+" : "=";
case Qt.Key_BracketLeft: return "[";
case Qt.Key_BraceLeft: return shift ? "{" : "[";
case Qt.Key_BracketRight: return "]";
case Qt.Key_BraceRight: return shift ? "}" : "]";
case Qt.Key_Backslash: return "\\";
case Qt.Key_Bar: return shift ? "|" : "\\";
case Qt.Key_Up: return "Up";
case Qt.Key_Down: return "Down";
case Qt.Key_Right: return "Right";
case Qt.Key_Left: return "Left";
case Qt.Key_Space: return "Space";
case Qt.Key_PageDown: return "PgDown";
case Qt.Key_PageUp: return "PgUp";
case Qt.Key_0: return "0";
case Qt.Key_1: return "1";
case Qt.Key_2: return "2";
case Qt.Key_3: return "3";
case Qt.Key_4: return "4";
case Qt.Key_5: return "5";
case Qt.Key_6: return "6";
case Qt.Key_7: return "7";
case Qt.Key_8: return "8";
case Qt.Key_9: return "9";
case Qt.Key_Exclam: return shift ? "!" : "1";
case Qt.Key_At: return shift ? "@" : "2";
case Qt.Key_NumberSign: return shift ? "#" : "3";
case Qt.Key_Dollar: return shift ? "$" : "4";
case Qt.Key_Percent: return shift ? "%" : "5";
case Qt.Key_AsciiCircum: return shift ? "^" : "6";
case Qt.Key_Ampersand: return shift ? "&" : "7";
case Qt.Key_Asterisk: return shift ? "*" : "8";
case Qt.Key_ParenLeft: return shift ? "(" : "9";
case Qt.Key_ParenRight: return shift ? ")" : "0";
case Qt.Key_A: return "A";
case Qt.Key_B: return "B";
case Qt.Key_C: return "C";
case Qt.Key_D: return "D";
case Qt.Key_E: return "E";
case Qt.Key_F: return "F";
case Qt.Key_G: return "G";
case Qt.Key_H: return "H";
case Qt.Key_I: return "I";
case Qt.Key_J: return "J";
case Qt.Key_K: return "K";
case Qt.Key_L: return "L";
case Qt.Key_M: return "M";
case Qt.Key_N: return "N";
case Qt.Key_O: return "O";
case Qt.Key_P: return "P";
case Qt.Key_Q: return "Q";
case Qt.Key_R: return "R";
case Qt.Key_S: return "S";
case Qt.Key_T: return "T";
case Qt.Key_U: return "U";
case Qt.Key_V: return "V";
case Qt.Key_W: return "W";
case Qt.Key_X: return "X";
case Qt.Key_Y: return "Y";
case Qt.Key_Z: return "Z";
case Qt.Key_F1: return "F1";
case Qt.Key_F2: return "F2";
case Qt.Key_F3: return "F3";
case Qt.Key_F4: return "F4";
case Qt.Key_F5: return "F5";
case Qt.Key_F6: return "F6";
case Qt.Key_F7: return "F7";
case Qt.Key_F8: return "F8";
case Qt.Key_F9: return "F9";
case Qt.Key_F10: return "F10";
case Qt.Key_F11: return "F11";
case Qt.Key_F12: return "F12";
case Qt.Key_Home: return "Home";
case Qt.Key_End: return "End";
case Qt.Key_Insert: return "Insert";
case Qt.Key_Delete: return "Delete";
}
return "";
}
}
background: Rectangle{
border.color: FluTheme.dark ? "#505050" : "#DFDFDF"
border.width: 1
implicitHeight: 42
implicitWidth: layout_row.width+28
radius: control.radius
color:control.color
FluFocusRectangle{
visible: control.activeFocus
}
}
component ItemKey:Rectangle{
id:item_key_control
property string text : ""
color:FluTheme.primaryColor
width: Math.max(item_text.implicitWidth+12,28)
height: Math.max(item_text.implicitHeight,28)
radius: 4
Text{
id:item_text
color: FluTheme.dark ? Qt.rgba(0,0,0,1) : Qt.rgba(1,1,1,1)
font.pixelSize: 13
text: item_key_control.text
anchors.centerIn: parent
}
}
Row{
id:layout_row
spacing: 5
anchors.centerIn: parent
Repeater{
model: control.current
delegate: ItemKey{
text: modelData
}
}
Item{
width: 3
height: 1
}
FluIcon{
iconSource: FluentIcons.EditMirrored
iconSize: 13
anchors{
verticalCenter: parent.verticalCenter
}
}
}
FluContentDialog{
id:content_dialog
property var keysModel: []
title: control.title
message: control.message
buttonFlags: FluContentDialogType.NegativeButton | FluContentDialogType.PositiveButton | FluContentDialogType.NeutralButton
positiveText: control.positiveText
neutralText: control.neutralText
negativeText: control.negativeText
onVisibleChanged: {
if(visible){
content_dialog.keysModel = control.current
}
}
onPositiveClicked: {
control.current = content_dialog.keysModel
control.accepted()
}
onNegativeClickListener: function(){
content_dialog.keysModel = control.current
}
contentDelegate: Component{
Item{
width: parent.width
height: 100
Component.onCompleted: {
forceActiveFocus()
}
Keys.enabled: true
Keys.onPressed:
(event)=>{
var keyNames = []
if (event.modifiers & Qt.AltModifier) {
keyNames.push("Alt")
}
if (event.modifiers & Qt.ControlModifier) {
keyNames.push("Ctrl")
}
if (event.modifiers & Qt.ShiftModifier) {
keyNames.push("Shift")
}
var keyName = d.keyToString(event.key,false)
if(keyName!==""){
keyNames.push(keyName)
content_dialog.keysModel = keyNames
}
event.accepted = true
}
Keys.onTabPressed:
(event)=>{
event.accepted = true
}
Row{
spacing: 5
anchors.centerIn: parent
Repeater{
model: content_dialog.keysModel
delegate: ItemKey{
text: modelData
}
}
}
}
}
}
onClicked: {
content_dialog.open()
}
}

View File

@ -17,14 +17,14 @@ Button {
if(checked){ if(checked){
return FluTheme.dark ? Qt.darker(normalColor,1.1) : Qt.lighter(normalColor,1.1) return FluTheme.dark ? Qt.darker(normalColor,1.1) : Qt.lighter(normalColor,1.1)
}else{ }else{
return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1) return FluTheme.dark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(246/255,246/255,246/255,1)
} }
} }
property color disableColor: { property color disableColor: {
if(checked){ if(checked){
return FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1) return FluTheme.dark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1)
}else{ }else{
return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1) return FluTheme.dark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(244/255,244/255,244/255,1)
} }
} }
property var clickListener : function(){ property var clickListener : function(){
@ -38,6 +38,7 @@ Button {
focusPolicy:Qt.TabFocus focusPolicy:Qt.TabFocus
id: control id: control
enabled: !disabled enabled: !disabled
verticalPadding: 0
horizontalPadding:12 horizontalPadding:12
onClicked: clickListener() onClicked: clickListener()
background: Rectangle{ background: Rectangle{

View File

@ -2,10 +2,10 @@ import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import FluentUI import FluentUI
import org.wangwenx190.FramelessHelper
Window { Window {
default property alias content: container.data default property alias content: layout_content.data
property string windowIcon: FluApp.windowIcon
property bool closeDestory: true property bool closeDestory: true
property int launchMode: FluWindowType.Standard property int launchMode: FluWindowType.Standard
property var argument:({}) property var argument:({})
@ -15,13 +15,13 @@ Window {
property bool fitsAppBarWindows: false property bool fitsAppBarWindows: false
property Item appBar: FluAppBar { property Item appBar: FluAppBar {
title: window.title title: window.title
width: window.width
height: 30 height: 30
showDark: window.showDark showDark: window.showDark
showClose: window.showClose showClose: window.showClose
showMinimize: window.showMinimize showMinimize: window.showMinimize
showMaximize: window.showMaximize showMaximize: window.showMaximize
showStayTop: window.showStayTop showStayTop: window.showStayTop
icon: window.windowIcon
} }
property color backgroundColor: { property color backgroundColor: {
if(active){ if(active){
@ -37,8 +37,10 @@ Window {
property bool showMinimize: true property bool showMinimize: true
property bool showMaximize: true property bool showMaximize: true
property bool showStayTop: true property bool showStayTop: true
property bool useSystemAppBar
property bool autoMaximize: false property bool autoMaximize: false
property bool useSystemAppBar
property color resizeBorderColor: FluTheme.dark ? Qt.rgba(80/255,80/255,80/255,1) : Qt.rgba(210/255,210/255,210/255,1)
property int resizeBorderWidth: 1
property var closeListener: function(event){ property var closeListener: function(event){
if(closeDestory){ if(closeDestory){
destoryOnClose() destoryOnClose()
@ -50,28 +52,25 @@ Window {
signal initArgument(var argument) signal initArgument(var argument)
signal firstVisible() signal firstVisible()
id:window id:window
maximumWidth: useSystemAppBar&&fixSize ? width : 16777215 maximumWidth: fixSize ? width : 16777215
maximumHeight: useSystemAppBar&&fixSize ? height : 16777215 maximumHeight: fixSize ? height : 16777215
minimumWidth: useSystemAppBar&&fixSize ? width : 0 minimumWidth: fixSize ? width : 0
minimumHeight: useSystemAppBar&&fixSize ? height : 0 minimumHeight: fixSize ? height : 0
color:"transparent" color:"transparent"
onStayTopChanged: {
d.changedStayTop()
}
Component.onCompleted: { Component.onCompleted: {
useSystemAppBar = FluApp.useSystemAppBar useSystemAppBar = FluApp.useSystemAppBar
if(!useSystemAppBar){
loader_frameless.sourceComponent = com_frameless
}
lifecycle.onCompleted(window) lifecycle.onCompleted(window)
initArgument(argument) initArgument(argument)
d.changedStayTop() moveWindowToDesktopCenter()
if(useSystemAppBar){
window.moveWindowToDesktopCenter()
if(window.autoMaximize){ if(window.autoMaximize){
window.showMaximized() window.showMaximized()
}else{ }else{
window.show() window.show()
} }
} }
}
Component.onDestruction: { Component.onDestruction: {
lifecycle.onDestruction() lifecycle.onDestruction()
} }
@ -85,73 +84,26 @@ Window {
QtObject{ QtObject{
id:d id:d
property bool isFirstVisible: true property bool isFirstVisible: true
function changedStayTop(){
function toggleStayTop(){
if(window.stayTop){
window.flags = window.flags | Qt.WindowStaysOnTopHint
}else{
window.flags = window.flags &~ Qt.WindowStaysOnTopHint
}
}
if(window.visibility === Window.Maximized){
window.visibility = Window.Windowed
toggleStayTop()
window.visibility = Window.Maximized
}else{
toggleStayTop()
}
}
} }
Connections{ Connections{
target: window target: window
function onClosing(event){closeListener(event)} function onClosing(event){closeListener(event)}
} }
Component{
id:com_frameless
FluFramelessHelper{}
}
Component{ Component{
id:com_background id:com_background
Rectangle{ Rectangle{
color: window.backgroundColor color: window.backgroundColor
} }
} }
FluLoader{
anchors.fill: parent
sourceComponent: background
}
FluLoader{
id:loader_app_bar
anchors {
top: parent.top
left: parent.left
right: parent.right
}
sourceComponent: window.useSystemAppBar ? undefined : com_app_bar
}
Component{ Component{
id:com_app_bar id:com_app_bar
Item{ Item{
data: window.appBar data: window.appBar
height: {
if(FluApp.useSystemAppBar){
return 0
} }
return window.fitsAppBarWindows ? 0 : childrenRect.height
}
}
}
Item{
id:container
anchors{
top: loader_app_bar.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
clip: true
}
FluLoader{
property string loadingText: "加载中..."
property bool cancel: false
id:loader_loading
anchors.fill: container
} }
Component{ Component{
id:com_loading id:com_loading
@ -215,64 +167,94 @@ Window {
} }
} }
} }
FluLoader{
id:loader_frameless
}
Item{
id:layout_container
property int offsetX: {
if(window.visibility === Window.Maximized){
var dx = window.x-Screen.virtualX
if(dx<0){
return Math.abs(dx)
}
}
return 0
}
property int offsetY: {
if(window.visibility === Window.Maximized){
var dy = window.y-Screen.virtualY
if(dy<0){
return Math.abs(dy)
}
}
return 0
}
anchors{
fill:parent
leftMargin: offsetX
rightMargin: offsetX
topMargin: offsetY
bottomMargin: offsetY
}
onWidthChanged: {
window.appBar.width = width
}
FluLoader{
anchors.fill: parent
sourceComponent: background
}
FluLoader{
id:loader_app_bar
anchors {
top: parent.top
left: parent.left
right: parent.right
}
height: {
if(window.useSystemAppBar){
return 0
}
return window.fitsAppBarWindows ? 0 : window.appBar.height
}
sourceComponent: window.useSystemAppBar ? undefined : com_app_bar
}
Item{
id:layout_content
anchors{
top: loader_app_bar.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
clip: true
}
FluLoader{
property string loadingText: "加载中..."
property bool cancel: false
id:loader_loading
anchors.fill: layout_content
}
FluInfoBar{ FluInfoBar{
id:infoBar id:infoBar
root: window root: window
} }
Connections{
target: FluTheme
function onDarkChanged(){
if (FluTheme.dark)
FramelessUtils.systemTheme = FramelessHelperConstants.Dark
else
FramelessUtils.systemTheme = FramelessHelperConstants.Light
}
}
FramelessHelper{
id:framless_helper
onReady: {
flags = flags | Qt.Window | Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint | Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint
if(appBar){
var appbar = window.appBar
window.moveWindowToDesktopCenter()
setWindowFixedSize(fixSize)
if (blurBehindWindowEnabled)
window.background = undefined
}
if(window.autoMaximize){
window.showMaximized()
}else{
window.show()
}
}
}
WindowLifecycle{ WindowLifecycle{
id:lifecycle id:lifecycle
} }
FluLoader{
id:loader_window_border
anchors.fill: parent
z:999
sourceComponent: window.useSystemAppBar ? undefined : com_window_border
}
Component{
id:com_window_border
Item{
WindowBorder{
anchors.fill: parent
visible: !FluTools.isLinux()
}
Rectangle{ Rectangle{
anchors.fill: parent anchors.fill: parent
color: Qt.rgba(0,0,0,0) color:"transparent"
border.width: 1 border.width: window.resizeBorderWidth
visible: FluTools.isLinux() border.color: window.resizeBorderColor
border.color: { visible: {
if(window.active){ if(window.useSystemAppBar){
return Qt.rgba(51/255,51/255,51/255,1) return false
} }
return Qt.rgba(153/255,153/255,153/255,1) if(window.visibility == Window.Maximized || window.visibility == Window.FullScreen){
return false
} }
return true
} }
} }
} }
@ -303,15 +285,17 @@ Window {
return lifecycle.createRegister(window,path) return lifecycle.createRegister(window,path)
} }
function moveWindowToDesktopCenter(){ function moveWindowToDesktopCenter(){
window.x = (Screen.desktopAvailableWidth - window.width)/2 window.setGeometry((Screen.width-window.width)/2+Screen.virtualX,(Screen.height-window.height)/2+Screen.virtualY,window.width,window.height)
window.y = (Screen.desktopAvailableHeight - window.height)/2
} }
function onResult(data){ function onResult(data){
if(_pageRegister){ if(_pageRegister){
_pageRegister.onResult(data) _pageRegister.onResult(data)
} }
} }
function containerItem(){ function layoutContainer(){
return container return layout_container
}
function layoutContent(){
return layout_content
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Some files were not shown because too many files have changed in this diff Show More