Compare commits
48 Commits
Author | SHA1 | Date | |
---|---|---|---|
70e525f51e | |||
72610da66e | |||
fde55d254c | |||
61659b5e31 | |||
f4112ee5dc | |||
f973f006d2 | |||
38ea91964e | |||
af6e39d8c0 | |||
6d2a8cde7a | |||
2bd0a831e7 | |||
1bf992ed69 | |||
ecd0f29d30 | |||
5e38493403 | |||
c5aad9feed | |||
d347512486 | |||
136e2c72af | |||
95f48b51bf | |||
7ba06d183d | |||
9ee50a585a | |||
c95ac86377 | |||
5787e308dd | |||
08c458c2a1 | |||
299eba18ac | |||
6da8117056 | |||
e5668869b9 | |||
65905b139e | |||
6974b0efa6 | |||
3c924bb0de | |||
ec2378a07a | |||
863c88411b | |||
6b6dbf27a1 | |||
dc37a151c8 | |||
6c86e61916 | |||
33c203fcb3 | |||
7086df10f0 | |||
13223a11a2 | |||
3d65bdc913 | |||
c80689e376 | |||
1abbc4593a | |||
c1ffce06aa | |||
bd8a561590 | |||
eed96b4c0e | |||
1b4fddec61 | |||
2c16f6f71a | |||
3770969097 | |||
d255f5881e | |||
711411f6a8 | |||
f5a4fc1300 |
@ -30,6 +30,7 @@ SolidCompression=yes
|
||||
WizardStyle=modern
|
||||
UninstallDisplayIcon={app}\{#MyAppExeName}
|
||||
SetupIconFile=.\..\favicon.ico
|
||||
MinVersion = 6.0
|
||||
|
||||
[Languages]
|
||||
Name: "chinesesimplified"; MessagesFile: "compiler:Languages\ChineseSimplified.isl"
|
||||
|
6
.gitmodules
vendored
@ -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
|
@ -1,6 +1,6 @@
|
||||
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})
|
||||
list(APPEND CMAKE_MODULE_PATH ${FLUENTUI_DIRECTORY}/.cmake/)
|
||||
@ -25,17 +25,16 @@ if(NOT FLUENTUI_QML_PLUGIN_DIRECTORY)
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(zxing-cpp)
|
||||
|
||||
target_compile_definitions(fluentuiplugin
|
||||
PRIVATE
|
||||
QT_MESSAGELOGCONTEXT
|
||||
)
|
||||
|
||||
if (FLUENTUI_BUILD_EXAMPLES)
|
||||
add_subdirectory(example)
|
||||
endif ()
|
||||
|
||||
set(FRAMELESSHELPER_BUILD_STATIC ON)
|
||||
set(FRAMELESSHELPER_NO_DEBUG_OUTPUT ON)
|
||||
set(FRAMELESSHELPER_BUILD_WIDGETS OFF)
|
||||
add_subdirectory(framelesshelper)
|
||||
|
||||
message("------------------------ FluentUI ------------------------")
|
||||
message("Build FluentUI demo applications.: ${FLUENTUI_BUILD_EXAMPLES}")
|
||||
message("Build static library.: ${FLUENTUI_BUILD_STATIC_LIB}")
|
||||
|
@ -1,12 +1,10 @@
|
||||
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)
|
||||
if(APPLE)
|
||||
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
#导入exmaple的QML位置,不然import example有时候会爆红
|
||||
set(QML_IMPORT_PATH ${CMAKE_BINARY_DIR}/example CACHE STRING "Qt Creator extra QML import paths" FORCE)
|
||||
@ -79,10 +77,10 @@ if(WIN32)
|
||||
${FLUENTUI_DIRECTORY}/.cmake/version_exe.rc.in
|
||||
${EXAMPLE_VERSION_RC_PATH}
|
||||
)
|
||||
configure_file(
|
||||
${FLUENTUI_DIRECTORY}/.cmake/InstallerScript.iss.in
|
||||
${FLUENTUI_DIRECTORY}/action-cli/InstallerScript.iss
|
||||
)
|
||||
configure_file(
|
||||
${FLUENTUI_DIRECTORY}/.cmake/InstallerScript.iss.in
|
||||
${FLUENTUI_DIRECTORY}/action-cli/InstallerScript.iss
|
||||
)
|
||||
endif()
|
||||
|
||||
#添加可执行文件
|
||||
@ -155,6 +153,11 @@ set_target_properties(example PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
target_compile_definitions(example
|
||||
PRIVATE
|
||||
QT_MESSAGELOGCONTEXT
|
||||
)
|
||||
|
||||
target_link_libraries(example PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Quick
|
||||
Qt${QT_VERSION_MAJOR}::Svg
|
||||
|
@ -134,7 +134,6 @@
|
||||
<file>qml/page/T_CalendarPicker.qml</file>
|
||||
<file>qml/page/T_Captcha.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_ColorPicker.qml</file>
|
||||
<file>qml/page/T_ComboBox.qml</file>
|
||||
@ -190,5 +189,12 @@
|
||||
<file>qml/global/Lang.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>
|
||||
</RCC>
|
||||
|
@ -16,21 +16,19 @@ Item {
|
||||
|
||||
Connections{
|
||||
target: FluApp
|
||||
function onVsyncChanged(){
|
||||
SettingsHelper.saveVsync(FluApp.vsync)
|
||||
}
|
||||
function onUseSystemAppBarChanged(){
|
||||
SettingsHelper.saveUseSystemAppBar(FluApp.useSystemAppBar)
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
FluNetwork.openLog = false
|
||||
FluNetwork.setInterceptor(function(param){
|
||||
param.addHeader("Token","000000000000000000000")
|
||||
})
|
||||
FluApp.init(app)
|
||||
FluApp.windowIcon = "qrc:/example/res/image/favicon.ico"
|
||||
FluApp.useSystemAppBar = SettingsHelper.getUseSystemAppBar()
|
||||
FluApp.vsync = SettingsHelper.getVsync()
|
||||
FluTheme.darkMode = SettingsHelper.getDarkMode()
|
||||
FluTheme.enableAnimation = true
|
||||
FluApp.routes = {
|
||||
|
132
example/qml-Qt6/chart/T_BarChart.qml
Normal 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
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
74
example/qml-Qt6/chart/T_BubbleChart.qml
Normal 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'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
45
example/qml-Qt6/chart/T_LineChart.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
93
example/qml-Qt6/chart/T_PieChart.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
57
example/qml-Qt6/chart/T_PolarAreaChart.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
74
example/qml-Qt6/chart/T_RadarChart.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
123
example/qml-Qt6/chart/T_ScatterChart.qml
Normal 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
|
||||
},
|
||||
}],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -368,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{
|
||||
spacing:10
|
||||
size:1
|
||||
@ -406,12 +453,6 @@ FluObject{
|
||||
url:"qrc:/example/qml/page/T_Captcha.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
FluPaneItem{
|
||||
title:"Chart"
|
||||
menuDelegate: paneItemMenu
|
||||
url:"qrc:/example/qml/page/T_Chart.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
FluPaneItem{
|
||||
title:"Network"
|
||||
menuDelegate: paneItemMenu
|
||||
|
@ -20,6 +20,14 @@ QtObject {
|
||||
property string locale
|
||||
property string navigation_view_display_mode
|
||||
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(){
|
||||
home="首页"
|
||||
@ -38,6 +46,14 @@ QtObject {
|
||||
locale="语言环境"
|
||||
navigation_view_display_mode="导航视图显示模式"
|
||||
other="其他"
|
||||
chart="表格"
|
||||
bar_chart="条形图"
|
||||
line_chart="折线图"
|
||||
pie_chart="饼图"
|
||||
polar_area_chart="极坐标区域图"
|
||||
bubble_chart="气泡图"
|
||||
scatter_chart="散点图"
|
||||
radar_chart="雷达图"
|
||||
}
|
||||
|
||||
function en(){
|
||||
@ -57,6 +73,14 @@ QtObject {
|
||||
locale="Locale"
|
||||
navigation_view_display_mode="NavigationView Display Mode"
|
||||
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
|
||||
|
@ -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'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -64,6 +64,20 @@ FluContentPage{
|
||||
.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{
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: 36
|
||||
@ -280,6 +294,21 @@ FluContentPage{
|
||||
.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{
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: 36
|
||||
|
@ -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{
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 20
|
||||
|
@ -13,14 +13,13 @@ FluWindow {
|
||||
|
||||
id:window
|
||||
title: "FluentUI"
|
||||
width: 1000
|
||||
height: 640
|
||||
width: 960
|
||||
height: 600
|
||||
minimumWidth: 520
|
||||
minimumHeight: 200
|
||||
launchMode: FluWindowType.SingleTask
|
||||
fitsAppBarWindows: true
|
||||
appBar: FluAppBar {
|
||||
width: window.width
|
||||
height: 30
|
||||
darkText: Lang.dark_mode
|
||||
showDark: true
|
||||
@ -42,7 +41,15 @@ FluWindow {
|
||||
}
|
||||
|
||||
onFirstVisible: {
|
||||
tour.open()
|
||||
timer_tour_delay.restart()
|
||||
}
|
||||
|
||||
Timer{
|
||||
id:timer_tour_delay
|
||||
interval: 200
|
||||
onTriggered: {
|
||||
tour.open()
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
@ -191,7 +198,12 @@ FluWindow {
|
||||
pageMode: FluNavigationViewType.NoStack
|
||||
items: ItemsOriginal
|
||||
footerItems:ItemsFooter
|
||||
topPadding:FluTools.isMacos() ? 20 : 0
|
||||
topPadding:{
|
||||
if(window.useSystemAppBar){
|
||||
return 0
|
||||
}
|
||||
return FluTools.isMacos() ? 20 : 0
|
||||
}
|
||||
displayMode:viewmodel_settings.displayMode
|
||||
logo: "qrc:/example/res/image/favicon.ico"
|
||||
title:"FluentUI"
|
||||
@ -228,7 +240,7 @@ FluWindow {
|
||||
id:com_reveal
|
||||
CircularReveal{
|
||||
id:reveal
|
||||
target:window.contentItem
|
||||
target:window.layoutContainer()
|
||||
anchors.fill: parent
|
||||
onAnimationFinished:{
|
||||
//动画结束后释放资源
|
||||
@ -253,8 +265,11 @@ FluWindow {
|
||||
if(!FluTheme.enableAnimation || window.fitsAppBarWindows === false){
|
||||
changeDark()
|
||||
}else{
|
||||
if(loader_reveal.sourceComponent){
|
||||
return
|
||||
}
|
||||
loader_reveal.sourceComponent = com_reveal
|
||||
var target = window.contentItem
|
||||
var target = window.layoutContainer()
|
||||
var pos = button.mapToItem(target,0,0)
|
||||
var mouseX = pos.x
|
||||
var mouseY = pos.y
|
||||
|
@ -16,21 +16,19 @@ Item {
|
||||
|
||||
Connections{
|
||||
target: FluApp
|
||||
function onVsyncChanged(){
|
||||
SettingsHelper.saveVsync(FluApp.vsync)
|
||||
}
|
||||
function onUseSystemAppBarChanged(){
|
||||
SettingsHelper.saveUseSystemAppBar(FluApp.useSystemAppBar)
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
FluNetwork.openLog = false
|
||||
FluNetwork.setInterceptor(function(param){
|
||||
param.addHeader("Token","000000000000000000000")
|
||||
})
|
||||
FluApp.init(app)
|
||||
FluApp.windowIcon = "qrc:/example/res/image/favicon.ico"
|
||||
FluApp.useSystemAppBar = SettingsHelper.getUseSystemAppBar()
|
||||
FluApp.vsync = SettingsHelper.getVsync()
|
||||
FluTheme.darkMode = SettingsHelper.getDarkMode()
|
||||
FluTheme.enableAnimation = true
|
||||
FluApp.routes = {
|
||||
|
133
example/qml/chart/T_BarChart.qml
Normal 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
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
75
example/qml/chart/T_BubbleChart.qml
Normal 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'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
46
example/qml/chart/T_LineChart.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
94
example/qml/chart/T_PieChart.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
58
example/qml/chart/T_PolarAreaChart.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
75
example/qml/chart/T_RadarChart.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
124
example/qml/chart/T_ScatterChart.qml
Normal 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
|
||||
},
|
||||
}],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -368,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{
|
||||
spacing:10
|
||||
size:1
|
||||
@ -406,12 +453,6 @@ FluObject{
|
||||
url:"qrc:/example/qml/page/T_Captcha.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
FluPaneItem{
|
||||
title:"Chart"
|
||||
menuDelegate: paneItemMenu
|
||||
url:"qrc:/example/qml/page/T_Chart.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
FluPaneItem{
|
||||
title:"Network"
|
||||
menuDelegate: paneItemMenu
|
||||
|
@ -20,6 +20,14 @@ QtObject {
|
||||
property string locale
|
||||
property string navigation_view_display_mode
|
||||
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(){
|
||||
home="首页"
|
||||
@ -38,6 +46,14 @@ QtObject {
|
||||
locale="语言环境"
|
||||
navigation_view_display_mode="导航视图显示模式"
|
||||
other="其他"
|
||||
chart="表格"
|
||||
bar_chart="条形图"
|
||||
line_chart="折线图"
|
||||
pie_chart="饼图"
|
||||
polar_area_chart="极坐标区域图"
|
||||
bubble_chart="气泡图"
|
||||
scatter_chart="散点图"
|
||||
radar_chart="雷达图"
|
||||
}
|
||||
|
||||
function en(){
|
||||
@ -57,6 +73,14 @@ QtObject {
|
||||
locale="Locale"
|
||||
navigation_view_display_mode="NavigationView Display Mode"
|
||||
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
|
||||
|
@ -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'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -65,6 +65,20 @@ FluContentPage{
|
||||
.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{
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: 36
|
||||
@ -281,6 +295,21 @@ FluContentPage{
|
||||
.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{
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: 36
|
||||
|
@ -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{
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 20
|
||||
|
@ -16,14 +16,13 @@ FluWindow {
|
||||
|
||||
id:window
|
||||
title: "FluentUI"
|
||||
width: 1000
|
||||
height: 640
|
||||
width: 960
|
||||
height: 600
|
||||
minimumWidth: 520
|
||||
minimumHeight: 200
|
||||
launchMode: FluWindowType.SingleTask
|
||||
fitsAppBarWindows: true
|
||||
appBar: FluAppBar {
|
||||
width: window.width
|
||||
height: 30
|
||||
darkText: Lang.dark_mode
|
||||
showDark: true
|
||||
@ -45,7 +44,15 @@ FluWindow {
|
||||
}
|
||||
|
||||
onFirstVisible: {
|
||||
tour.open()
|
||||
timer_tour_delay.restart()
|
||||
}
|
||||
|
||||
Timer{
|
||||
id:timer_tour_delay
|
||||
interval: 200
|
||||
onTriggered: {
|
||||
tour.open()
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
@ -194,7 +201,12 @@ FluWindow {
|
||||
pageMode: FluNavigationViewType.NoStack
|
||||
items: ItemsOriginal
|
||||
footerItems:ItemsFooter
|
||||
topPadding:FluTools.isMacos() ? 20 : 0
|
||||
topPadding:{
|
||||
if(window.useSystemAppBar){
|
||||
return 0
|
||||
}
|
||||
return FluTools.isMacos() ? 20 : 0
|
||||
}
|
||||
displayMode:viewmodel_settings.displayMode
|
||||
logo: "qrc:/example/res/image/favicon.ico"
|
||||
title:"FluentUI"
|
||||
@ -231,7 +243,7 @@ FluWindow {
|
||||
id:com_reveal
|
||||
CircularReveal{
|
||||
id:reveal
|
||||
target:window.contentItem
|
||||
target:window.layoutContainer()
|
||||
anchors.fill: parent
|
||||
onAnimationFinished:{
|
||||
//动画结束后释放资源
|
||||
@ -256,8 +268,11 @@ FluWindow {
|
||||
if(!FluTheme.enableAnimation || window.fitsAppBarWindows === false){
|
||||
changeDark()
|
||||
}else{
|
||||
if(loader_reveal.sourceComponent){
|
||||
return
|
||||
}
|
||||
loader_reveal.sourceComponent = com_reveal
|
||||
var target = window.contentItem
|
||||
var target = window.layoutContainer()
|
||||
var pos = button.mapToItem(target,0,0)
|
||||
var mouseX = pos.x
|
||||
var mouseY = pos.y
|
||||
|
@ -5,10 +5,11 @@
|
||||
|
||||
CircularReveal::CircularReveal(QQuickItem* parent) : QQuickPaintedItem(parent)
|
||||
{
|
||||
_anim = new QPropertyAnimation(this, "radius", this);
|
||||
setVisible(false);
|
||||
_anim.setDuration(333);
|
||||
_anim.setEasingCurve(QEasingCurve::OutCubic);
|
||||
connect(&_anim, &QPropertyAnimation::finished,this,[=](){
|
||||
_anim->setDuration(333);
|
||||
_anim->setEasingCurve(QEasingCurve::OutCubic);
|
||||
connect(_anim, &QPropertyAnimation::finished,this,[=](){
|
||||
update();
|
||||
setVisible(false);
|
||||
Q_EMIT animationFinished();
|
||||
@ -31,8 +32,8 @@ void CircularReveal::paint(QPainter* painter)
|
||||
}
|
||||
|
||||
void CircularReveal::start(int w,int h,const QPoint& center,int radius){
|
||||
_anim.setStartValue(0);
|
||||
_anim.setEndValue(radius);
|
||||
_anim->setStartValue(0);
|
||||
_anim->setEndValue(radius);
|
||||
_center = center;
|
||||
_grabResult = _target->grabToImage(QSize(w,h));
|
||||
connect(_grabResult.data(), &QQuickItemGrabResult::ready, this, &CircularReveal::handleGrabResult);
|
||||
@ -43,5 +44,5 @@ void CircularReveal::handleGrabResult(){
|
||||
update();
|
||||
setVisible(true);
|
||||
Q_EMIT imageChanged();
|
||||
_anim.start();
|
||||
_anim->start();
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ public:
|
||||
Q_SIGNAL void animationFinished();
|
||||
Q_SLOT void handleGrabResult();
|
||||
private:
|
||||
QPropertyAnimation* _anim = nullptr;
|
||||
QImage _source;
|
||||
QPropertyAnimation _anim = QPropertyAnimation(this, "radius", this);
|
||||
QPoint _center;
|
||||
QSharedPointer<QQuickItemGrabResult> _grabResult;
|
||||
};
|
||||
|
@ -2,7 +2,20 @@
|
||||
#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))
|
||||
@ -13,40 +26,143 @@
|
||||
#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 inline void myMessageHandler(const QtMsgType type, const QMessageLogContext &context, const QString &message)
|
||||
static int g_logLevel = 4;
|
||||
|
||||
std::map<QtMsgType, int> logLevelMap = {
|
||||
{QtFatalMsg,0},
|
||||
{QtCriticalMsg,1},
|
||||
{QtWarningMsg,2},
|
||||
{QtInfoMsg,3},
|
||||
{QtDebugMsg,4}
|
||||
};
|
||||
|
||||
QString Log::prettyProductInfoWrapper()
|
||||
{
|
||||
if (message.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
const QString finalMessage = qFormatLogMessage(type, context, message).trimmed();
|
||||
if ((type == QtInfoMsg) || (type == QtDebugMsg)) {
|
||||
std::cout << qUtf8Printable(finalMessage) << std::endl;
|
||||
} else {
|
||||
std::cerr << qUtf8Printable(finalMessage) << std::endl;
|
||||
}
|
||||
if (g_logError) {
|
||||
return;
|
||||
}
|
||||
if (!g_logFile) {
|
||||
g_logFile = std::make_unique<QFile>();
|
||||
g_logFile->setFileName(QString("debug-%1.log").arg(g_app));
|
||||
if (!g_logFile->open(QFile::WriteOnly | QFile::Text | QFile::Append)) {
|
||||
std::cerr << "Can't open file to write: " << qUtf8Printable(g_logFile->errorString()) << std::endl;
|
||||
g_logFile.reset();
|
||||
g_logError = true;
|
||||
return;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!g_logStream) {
|
||||
g_logStream = std::make_unique<QTextStream>();
|
||||
g_logStream->setDevice(g_logFile.get());
|
||||
#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();
|
||||
}
|
||||
(*g_logStream) << finalMessage << QT_ENDL;
|
||||
}
|
||||
|
||||
void Log::setup(const QString &app)
|
||||
@ -61,9 +177,28 @@ void Log::setup(const QString &app)
|
||||
}
|
||||
once = true;
|
||||
g_app = app;
|
||||
qSetMessagePattern(QString(
|
||||
"[%{time yyyy/MM/dd hh:mm:ss.zzz}] <%{if-info}INFO%{endif}%{if-debug}DEBUG"
|
||||
"%{endif}%{if-warning}WARNING%{endif}%{if-critical}CRITICAL%{endif}%{if-fatal}"
|
||||
"FATAL%{endif}> %{if-category}%{category}: %{endif}%{message}"));
|
||||
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()<<"===================================================";
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
namespace Log
|
||||
{
|
||||
QString prettyProductInfoWrapper();
|
||||
void setup(const QString &app);
|
||||
}
|
||||
|
||||
|
@ -12,23 +12,15 @@ SettingsHelper::~SettingsHelper() = default;
|
||||
|
||||
void SettingsHelper::save(const QString& key,QVariant val)
|
||||
{
|
||||
QByteArray data = {};
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream.setVersion(QDataStream::Qt_5_6);
|
||||
stream << val;
|
||||
m_settings->setValue(key, data);
|
||||
m_settings->setValue(key, val);
|
||||
}
|
||||
|
||||
QVariant SettingsHelper::get(const QString& key,QVariant def){
|
||||
const QByteArray data = m_settings->value(key).toByteArray();
|
||||
if (data.isEmpty()) {
|
||||
return def;
|
||||
QVariant data = m_settings->value(key);
|
||||
if (!data.isNull() && data.isValid()) {
|
||||
return data;
|
||||
}
|
||||
QDataStream stream(data);
|
||||
stream.setVersion(QDataStream::Qt_5_6);
|
||||
QVariant val;
|
||||
stream >> val;
|
||||
return val;
|
||||
return def;
|
||||
}
|
||||
|
||||
void SettingsHelper::init(char *argv[]){
|
||||
@ -36,6 +28,5 @@ void SettingsHelper::init(char *argv[]){
|
||||
const QFileInfo fileInfo(applicationPath);
|
||||
const QString iniFileName = fileInfo.completeBaseName() + ".ini";
|
||||
const QString iniFilePath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/" + iniFileName;
|
||||
qDebug()<<"Application configuration file path->"<<iniFilePath;
|
||||
m_settings.reset(new QSettings(iniFilePath, QSettings::IniFormat));
|
||||
}
|
||||
|
@ -20,13 +20,11 @@ public:
|
||||
~SettingsHelper() override;
|
||||
void init(char *argv[]);
|
||||
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 QVariant getDarkMode(){return get("darkMode",QVariant(0));}
|
||||
Q_INVOKABLE void saveVsync(bool vsync){save("vsync",vsync);}
|
||||
Q_INVOKABLE QVariant getVsync(){return get("vsync",QVariant(true));}
|
||||
Q_INVOKABLE int getDarkMode(){return get("darkMode",QVariant(0)).toInt();}
|
||||
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:
|
||||
void save(const QString& key,QVariant val);
|
||||
QVariant get(const QString& key,QVariant def={});
|
||||
|
@ -24,8 +24,18 @@ Q_IMPORT_QML_PLUGIN(FluentUIPlugin)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
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");
|
||||
QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
@ -33,11 +43,6 @@ int main(int argc, char *argv[])
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
#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 (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
QQuickWindow::setGraphicsApi(QSGRendererInterface::Software);
|
||||
@ -55,7 +60,6 @@ int main(int argc, char *argv[])
|
||||
#ifdef FLUENTUI_BUILD_STATIC_LIB
|
||||
FluentUI::getInstance()->registerTypes(&engine);
|
||||
#endif
|
||||
qDebug()<<engine.importPathList();
|
||||
qmlRegisterType<CircularReveal>("example", 1, 0, "CircularReveal");
|
||||
qmlRegisterType<FileWatcher>("example", 1, 0, "FileWatcher");
|
||||
qmlRegisterType<FpsItem>("example", 1, 0, "FpsItem");
|
||||
|
@ -1,16 +1,14 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
if (FLUENTUI_BUILD_STATIC_LIB AND (QT_VERSION VERSION_GREATER_EQUAL "6.2"))
|
||||
project(fluentui LANGUAGES CXX)
|
||||
project(fluentui VERSION 1.0)
|
||||
else()
|
||||
project(fluentuiplugin LANGUAGES CXX)
|
||||
project(fluentuiplugin VERSION 1.0)
|
||||
endif()
|
||||
|
||||
#配置通用编译
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
if(APPLE)
|
||||
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
if (FLUENTUI_BUILD_STATIC_LIB)
|
||||
add_definitions(-DFLUENTUI_BUILD_STATIC_LIB)
|
||||
@ -120,11 +118,14 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
HAVE_CONFIG_H
|
||||
)
|
||||
|
||||
#去掉mingw生成的动态库libxxx前缀lib,不去掉前缀会导致 module "FluentUI" plugin "fluentuiplugin" not found
|
||||
if(MINGW)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX ".debug")
|
||||
endif()
|
||||
|
||||
#MSVC Debug 添加后缀d,与Qt插件风格保持一致
|
||||
@ -137,9 +138,6 @@ target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
Qt${QT_VERSION_MAJOR}::CorePrivate
|
||||
Qt${QT_VERSION_MAJOR}::QuickPrivate
|
||||
Qt${QT_VERSION_MAJOR}::QmlPrivate
|
||||
ZXing
|
||||
FramelessHelper::Core
|
||||
FramelessHelper::Quick
|
||||
)
|
||||
|
||||
#安装
|
||||
|
@ -8,13 +8,8 @@
|
||||
#include <QUuid>
|
||||
#include <QFontDatabase>
|
||||
#include <QClipboard>
|
||||
#include <FramelessHelper/Quick/framelessquickmodule.h>
|
||||
#include <FramelessHelper/Core/private/framelessconfig_p.h>
|
||||
|
||||
FRAMELESSHELPER_USE_NAMESPACE
|
||||
|
||||
FluApp::FluApp(QObject *parent):QObject{parent}{
|
||||
connect(this,&FluApp::useSystemAppBarChanged,this,[=]{FramelessConfig::instance()->set(Global::Option::UseSystemAppBar,_useSystemAppBar);});
|
||||
vsync(true);
|
||||
useSystemAppBar(false);
|
||||
}
|
||||
@ -24,11 +19,10 @@ FluApp::~FluApp(){
|
||||
|
||||
void FluApp::init(QObject *application){
|
||||
this->_application = application;
|
||||
FramelessHelperQuickInitialize();
|
||||
FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial);
|
||||
FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow);
|
||||
QQmlEngine *engine = qmlEngine(_application);
|
||||
FramelessHelper::Quick::registerTypes(engine);
|
||||
QJSEngine * jsEngine = qjsEngine(_application);
|
||||
std::string jsFunction = R"( (function () { console.log("FluentUI");}) )";
|
||||
QJSValue function = jsEngine->evaluate(QString::fromStdString(jsFunction));
|
||||
jsEngine->globalObject().setProperty("__fluentui",function);
|
||||
}
|
||||
|
||||
void FluApp::run(){
|
||||
|
@ -22,6 +22,7 @@ class FluApp : public QObject
|
||||
Q_PROPERTY_AUTO(QString,initialRoute);
|
||||
Q_PROPERTY_AUTO(QJsonObject,routes);
|
||||
Q_PROPERTY_AUTO(bool,useSystemAppBar);
|
||||
Q_PROPERTY_AUTO(QString,windowIcon);
|
||||
QML_NAMED_ELEMENT(FluApp)
|
||||
QML_SINGLETON
|
||||
private:
|
||||
|
256
src/FluFramelessHelper.cpp
Normal 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
@ -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
|
@ -54,6 +54,13 @@ int NetworkParams::getRetry(){
|
||||
return FluNetwork::getInstance()->retry();
|
||||
}
|
||||
|
||||
bool NetworkParams::getOpenLog(){
|
||||
if(!_openLog.isNull()){
|
||||
return _openLog.toBool();
|
||||
}
|
||||
return FluNetwork::getInstance()->openLog();
|
||||
}
|
||||
|
||||
DownloadParam::DownloadParam(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
@ -129,6 +136,11 @@ NetworkParams* NetworkParams::bind(QObject* target){
|
||||
return this;
|
||||
}
|
||||
|
||||
NetworkParams* NetworkParams::openLog(QVariant val){
|
||||
_openLog = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
QString NetworkParams::buildCacheKey(){
|
||||
QJsonObject obj;
|
||||
obj.insert("url",_url);
|
||||
@ -189,8 +201,8 @@ void FluNetwork::handle(NetworkParams* params,NetworkCallable* c){
|
||||
QNetworkRequest request(url);
|
||||
addHeaders(&request,params->_headerMap);
|
||||
QNetworkReply* reply;
|
||||
sendRequest(&manager,request,params,reply,callable);
|
||||
if(!QPointer(qApp)){
|
||||
sendRequest(&manager,request,params,reply,i==0,callable);
|
||||
if(!QPointer<QGuiApplication>(qApp)){
|
||||
reply->deleteLater();
|
||||
reply = nullptr;
|
||||
return;
|
||||
@ -215,22 +227,26 @@ void FluNetwork::handle(NetworkParams* params,NetworkCallable* c){
|
||||
disconnect(conn_quit);
|
||||
}
|
||||
QString response;
|
||||
if(reply->isOpen()){
|
||||
response = QString::fromUtf8(reply->readAll());
|
||||
if(params->_method == NetworkParams::METHOD_HEAD){
|
||||
response = headerList2String(reply->rawHeaderPairs());
|
||||
}else{
|
||||
if(reply->isOpen()){
|
||||
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(params->_cacheMode != FluNetworkType::CacheMode::NoCache){
|
||||
saveResponse(cacheKey,response);
|
||||
}
|
||||
callable->success(response);
|
||||
}
|
||||
printRequestEndLog(request,params,reply,response);
|
||||
break;
|
||||
}else{
|
||||
if(i == params->getRetry()-1){
|
||||
if(!callable.isNull()){
|
||||
int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if(params->_cacheMode == FluNetworkType::CacheMode::RequestFailedReadCache && cacheExists(cacheKey)){
|
||||
if(!callable.isNull()){
|
||||
callable->cache(readCache(cacheKey));
|
||||
@ -238,6 +254,7 @@ void FluNetwork::handle(NetworkParams* params,NetworkCallable* c){
|
||||
}
|
||||
callable->error(httpStatus,reply->errorString(),response);
|
||||
}
|
||||
printRequestEndLog(request,params,reply,response);
|
||||
}
|
||||
}
|
||||
reply->deleteLater();
|
||||
@ -387,40 +404,70 @@ QString FluNetwork::getCacheFilePath(const QString& 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();
|
||||
switch (params->_type) {
|
||||
case NetworkParams::TYPE_FORM:{
|
||||
QHttpMultiPart *multiPart = new QHttpMultiPart();
|
||||
multiPart->setContentType(QHttpMultiPart::FormDataType);
|
||||
for (const auto& each : params->_paramMap.toStdMap())
|
||||
{
|
||||
QHttpPart part;
|
||||
part.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"").arg(each.first));
|
||||
part.setBody(each.second.toByteArray());
|
||||
multiPart->append(part);
|
||||
}
|
||||
for (const auto& each : params->_fileMap.toStdMap())
|
||||
{
|
||||
QString filePath = each.second.toString();
|
||||
QString name = each.first;
|
||||
QFile *file = new QFile(filePath);
|
||||
QString fileName = QFileInfo(filePath).fileName();
|
||||
file->open(QIODevice::ReadOnly);
|
||||
file->setParent(multiPart);
|
||||
QHttpPart part;
|
||||
part.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"; filename=\"%2\"").arg(name,fileName));
|
||||
part.setBodyDevice(file);
|
||||
multiPart->append(part);
|
||||
}
|
||||
reply = manager->sendCustomRequest(request,verb,multiPart);
|
||||
multiPart->setParent(reply);
|
||||
if(!params->_fileMap.isEmpty()){
|
||||
bool isFormData = !params->_fileMap.isEmpty();
|
||||
if(isFormData){
|
||||
QHttpMultiPart *multiPart = new QHttpMultiPart();
|
||||
multiPart->setContentType(QHttpMultiPart::FormDataType);
|
||||
for (const auto& each : params->_paramMap.toStdMap())
|
||||
{
|
||||
QHttpPart part;
|
||||
part.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"").arg(each.first));
|
||||
part.setBody(each.second.toByteArray());
|
||||
multiPart->append(part);
|
||||
}
|
||||
for (const auto& each : params->_fileMap.toStdMap())
|
||||
{
|
||||
QString filePath = each.second.toString();
|
||||
QString name = each.first;
|
||||
QFile *file = new QFile(filePath);
|
||||
QString fileName = QFileInfo(filePath).fileName();
|
||||
file->open(QIODevice::ReadOnly);
|
||||
file->setParent(multiPart);
|
||||
QHttpPart part;
|
||||
part.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"; filename=\"%2\"").arg(name,fileName));
|
||||
part.setBodyDevice(file);
|
||||
multiPart->append(part);
|
||||
}
|
||||
reply = manager->sendCustomRequest(request,verb,multiPart);
|
||||
multiPart->setParent(reply);
|
||||
connect(reply,&QNetworkReply::uploadProgress,reply,[callable](qint64 bytesSent, qint64 bytesTotal){
|
||||
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;
|
||||
}
|
||||
@ -458,6 +505,46 @@ void FluNetwork::sendRequest(QNetworkAccessManager* manager,QNetworkRequest requ
|
||||
reply = manager->sendCustomRequest(request,verb);
|
||||
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){
|
||||
@ -471,6 +558,7 @@ void FluNetwork::saveResponse(QString key,QString response){
|
||||
}
|
||||
|
||||
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);
|
||||
while (iter.hasNext())
|
||||
{
|
||||
@ -494,6 +582,7 @@ FluNetwork::FluNetwork(QObject *parent): QObject{parent}
|
||||
{
|
||||
timeout(5000);
|
||||
retry(3);
|
||||
openLog(false);
|
||||
cacheDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation).append(QDir::separator()).append("network"));
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <QJsonValue>
|
||||
#include <QJSValue>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include "Def.h"
|
||||
#include "stdafx.h"
|
||||
#include "singleton.h"
|
||||
@ -67,11 +68,13 @@ public:
|
||||
Q_INVOKABLE NetworkParams* setCacheMode(int val);
|
||||
Q_INVOKABLE NetworkParams* toDownload(QString destPath,bool append = false);
|
||||
Q_INVOKABLE NetworkParams* bind(QObject* target);
|
||||
Q_INVOKABLE NetworkParams* openLog(QVariant val);
|
||||
Q_INVOKABLE void go(NetworkCallable* result);
|
||||
QString buildCacheKey();
|
||||
QString method2String();
|
||||
int getTimeout();
|
||||
int getRetry();
|
||||
bool getOpenLog();
|
||||
public:
|
||||
DownloadParam* _downloadParam = nullptr;
|
||||
QObject* _target = nullptr;
|
||||
@ -85,6 +88,7 @@ public:
|
||||
QMap<QString, QVariant> _fileMap;
|
||||
int _timeout = -1;
|
||||
int _retry = -1;
|
||||
QVariant _openLog;
|
||||
int _cacheMode = FluNetworkType::CacheMode::NoCache;
|
||||
};
|
||||
|
||||
@ -94,6 +98,7 @@ class FluNetwork : public QObject
|
||||
Q_PROPERTY_AUTO(int,timeout)
|
||||
Q_PROPERTY_AUTO(int,retry)
|
||||
Q_PROPERTY_AUTO(QString,cacheDir)
|
||||
Q_PROPERTY_AUTO(bool,openLog)
|
||||
QML_NAMED_ELEMENT(FluNetwork)
|
||||
QML_SINGLETON
|
||||
private:
|
||||
@ -123,13 +128,17 @@ public:
|
||||
void handle(NetworkParams* params,NetworkCallable* result);
|
||||
void handleDownload(NetworkParams* params,NetworkCallable* result);
|
||||
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 addHeaders(QNetworkRequest* request,const QMap<QString, QVariant>& headers);
|
||||
void saveResponse(QString key,QString response);
|
||||
QString readCache(const QString& key);
|
||||
bool cacheExists(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:
|
||||
QJSValue _interceptor;
|
||||
};
|
||||
|
@ -175,3 +175,7 @@ QPoint FluTools::cursorPos(){
|
||||
qint64 FluTools::currentTimestamp(){
|
||||
return QDateTime::currentMSecsSinceEpoch();
|
||||
}
|
||||
|
||||
QIcon FluTools::windowIcon(){
|
||||
return QGuiApplication::windowIcon();
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ public:
|
||||
Q_INVOKABLE bool isSoftware();
|
||||
Q_INVOKABLE qint64 currentTimestamp();
|
||||
Q_INVOKABLE QPoint cursorPos();
|
||||
Q_INVOKABLE QIcon windowIcon();
|
||||
};
|
||||
|
||||
#endif // FLUTOOLS_H
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "Screenshot.h"
|
||||
#include "FluRectangle.h"
|
||||
#include "FluNetwork.h"
|
||||
#include "FluFramelessHelper.h"
|
||||
#include "QRCode.h"
|
||||
|
||||
void FluentUI::registerTypes(QQmlEngine *engine){
|
||||
@ -40,6 +41,7 @@ void FluentUI::registerTypes(const char *uri){
|
||||
qmlRegisterType<FluRectangle>(uri,major,minor,"FluRectangle");
|
||||
qmlRegisterType<NetworkCallable>(uri,major,minor,"FluNetworkCallable");
|
||||
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/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){
|
||||
#ifdef Q_OS_WIN
|
||||
QFont font;
|
||||
font.setFamily("Microsoft YaHei UI");
|
||||
font.setFamily("微软雅黑");
|
||||
QGuiApplication::setFont(font);
|
||||
#endif
|
||||
FluApp* app = FluApp::getInstance();
|
||||
|
@ -1,10 +1,6 @@
|
||||
#include "QRCode.h"
|
||||
|
||||
#include "BarcodeFormat.h"
|
||||
#include "BitMatrix.h"
|
||||
#include "MultiFormatWriter.h"
|
||||
|
||||
using namespace ZXing;
|
||||
#include "qrcode/qrencode.h"
|
||||
|
||||
QRCode::QRCode(QQuickItem* parent):QQuickPaintedItem(parent){
|
||||
color(QColor(0,0,0,255));
|
||||
@ -27,29 +23,35 @@ void QRCode::paint(QPainter* painter){
|
||||
if(_text.isEmpty()){
|
||||
return;
|
||||
}
|
||||
if(_text.length()>1108){
|
||||
if(_text.length()>1024){
|
||||
return;
|
||||
}
|
||||
painter->save();
|
||||
auto format = ZXing::BarcodeFormatFromString("QRCode");
|
||||
auto writer = MultiFormatWriter(format);
|
||||
writer.setMargin(0);
|
||||
writer.setEncoding(ZXing::CharacterSet::UTF8);
|
||||
auto matrix = writer.encode(_text.toUtf8().constData(), 0, 0);
|
||||
auto bitmap = ToMatrix<uint8_t>(matrix);
|
||||
auto image = QImage(bitmap.data(), bitmap.width(), bitmap.height(), bitmap.width(), QImage::Format::Format_Grayscale8).copy();
|
||||
QImage rgbImage = image.convertToFormat(QImage::Format_ARGB32);
|
||||
for (int y = 0; y < rgbImage.height(); ++y) {
|
||||
for (int x = 0; x < rgbImage.width(); ++x) {
|
||||
QRgb pixel = rgbImage.pixel(x, y);
|
||||
if (qRed(pixel) == 0 && qGreen(pixel) == 0 && qBlue(pixel) == 0) {
|
||||
rgbImage.setPixelColor(x, y, _color);
|
||||
}
|
||||
if (qRed(pixel) == 255 && qGreen(pixel) == 255 && qBlue(pixel) == 255) {
|
||||
rgbImage.setPixelColor(x, y, _bgColor);
|
||||
QRcode *qrcode = QRcode_encodeString(_text.toUtf8().constData(), 2, QR_ECLEVEL_Q, QR_MODE_8, 1);
|
||||
qint32 w = width();
|
||||
qint32 h = height();
|
||||
qint32 qrcodeW = qrcode->width > 0 ? qrcode->width : 1;
|
||||
double scaleX = (double)w / (double)qrcodeW;
|
||||
double scaleY = (double)h / (double)qrcodeW;
|
||||
QImage image = QImage(w, h, QImage::Format_ARGB32);
|
||||
QPainter p(&image);
|
||||
p.setBrush(_bgColor);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawRect(0, 0, w, h);
|
||||
p.setBrush(_color);
|
||||
for (qint32 y = 0; y < qrcodeW; y++)
|
||||
{
|
||||
for (qint32 x = 0; x < qrcodeW; x++)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
@ -34,10 +34,17 @@ Rectangle{
|
||||
property bool isMac: FluTools.isMacos()
|
||||
property color borerlessColor : FluTheme.primaryColor
|
||||
property var maxClickListener : function(){
|
||||
if (d.win.visibility === Window.Maximized)
|
||||
d.win.visibility = Window.Windowed
|
||||
else
|
||||
d.win.visibility = Window.Maximized
|
||||
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)
|
||||
d.win.visibility = Window.Windowed
|
||||
else
|
||||
d.win.visibility = Window.Maximized
|
||||
}
|
||||
}
|
||||
property var minClickListener: function(){
|
||||
d.win.visibility = Window.Minimized
|
||||
@ -74,14 +81,16 @@ Rectangle{
|
||||
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)
|
||||
}
|
||||
TapHandler {
|
||||
onTapped: if (tapCount === 2 && d.resizable) btn_maximize.clicked()
|
||||
gesturePolicy: TapHandler.DragThreshold
|
||||
}
|
||||
DragHandler {
|
||||
target: null
|
||||
grabPermissions: TapHandler.CanTakeOverFromAnything
|
||||
onActiveChanged: if (active) { d.win.startSystemMove(); }
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onPositionChanged: {
|
||||
d.win.startSystemMove()
|
||||
}
|
||||
onDoubleClicked: {
|
||||
if(d.resizable){
|
||||
btn_maximize.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
Row{
|
||||
anchors{
|
||||
@ -105,6 +114,49 @@ Rectangle{
|
||||
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{
|
||||
anchors.right: parent.right
|
||||
height: control.height
|
||||
|
@ -4,25 +4,27 @@ import "./../JS/Chart.js" as Chart
|
||||
|
||||
Canvas {
|
||||
id: control
|
||||
property var window: Window.window
|
||||
property var jsChart: undefined
|
||||
property string chartType
|
||||
property var chartData
|
||||
property var chartOptions
|
||||
property double chartAnimationProgress: 0.1
|
||||
property int animationEasingType: Easing.InOutExpo
|
||||
property double animationDuration: 0
|
||||
property var memorizedContext
|
||||
property var memorizedData
|
||||
property var memorizedOptions
|
||||
property double animationDuration: 300
|
||||
property alias animationRunning: chartAnimator.running
|
||||
signal animationFinished()
|
||||
function animateToNewData()
|
||||
{
|
||||
chartAnimationProgress = 0.1;
|
||||
jsChart.update();
|
||||
d.jsChart.update();
|
||||
chartAnimator.restart();
|
||||
}
|
||||
QtObject{
|
||||
id:d
|
||||
property var jsChart: undefined
|
||||
property var memorizedContext
|
||||
property var memorizedData
|
||||
property var memorizedOptions
|
||||
}
|
||||
MouseArea {
|
||||
id: event
|
||||
anchors.fill: control
|
||||
@ -48,31 +50,33 @@ Canvas {
|
||||
mouseEvent.left = 0;
|
||||
mouseEvent.top = 0;
|
||||
mouseEvent.target = control;
|
||||
|
||||
if(handler) {
|
||||
handler(mouseEvent);
|
||||
}
|
||||
|
||||
control.requestPaint();
|
||||
}
|
||||
onClicked:(mouse)=> {
|
||||
submitEvent(mouse, "click");
|
||||
}
|
||||
onPositionChanged:(mouse)=> {
|
||||
submitEvent(mouse, "mousemove");
|
||||
}
|
||||
onClicked:
|
||||
(mouse)=> {
|
||||
submitEvent(mouse, "click");
|
||||
}
|
||||
onPositionChanged:
|
||||
(mouse)=> {
|
||||
submitEvent(mouse, "mousemove");
|
||||
}
|
||||
onExited: {
|
||||
submitEvent(undefined, "mouseout");
|
||||
}
|
||||
onEntered: {
|
||||
submitEvent(undefined, "mouseenter");
|
||||
}
|
||||
onPressed:(mouse)=> {
|
||||
submitEvent(mouse, "mousedown");
|
||||
}
|
||||
onReleased:(mouse)=> {
|
||||
submitEvent(mouse, "mouseup");
|
||||
}
|
||||
onPressed:
|
||||
(mouse)=> {
|
||||
submitEvent(mouse, "mousedown");
|
||||
}
|
||||
onReleased:
|
||||
(mouse)=> {
|
||||
submitEvent(mouse, "mouseup");
|
||||
}
|
||||
}
|
||||
PropertyAnimation {
|
||||
id: chartAnimator
|
||||
@ -90,34 +94,25 @@ Canvas {
|
||||
control.requestPaint();
|
||||
}
|
||||
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');
|
||||
|
||||
jsChart = Chart.build(ctx, {
|
||||
type: control.chartType,
|
||||
data: control.chartData,
|
||||
options: control.chartOptions
|
||||
});
|
||||
|
||||
memorizedData = control.chartData ;
|
||||
memorizedContext = control.getContext('2d');
|
||||
memorizedOptions = control.chartOptions;
|
||||
|
||||
control.jsChart.bindEvents(function(newHandler) {event.handler = newHandler;});
|
||||
|
||||
d.jsChart = Chart.build(ctx, {type: control.chartType,data: control.chartData,options: control.chartOptions});
|
||||
d.memorizedData = control.chartData ;
|
||||
d.memorizedContext = control.getContext('2d');
|
||||
d.memorizedOptions = control.chartOptions;
|
||||
d.jsChart.bindEvents(function(newHandler) {event.handler = newHandler;});
|
||||
chartAnimator.start();
|
||||
}
|
||||
|
||||
jsChart.draw(chartAnimationProgress);
|
||||
d.jsChart.draw(chartAnimationProgress);
|
||||
}
|
||||
onWidthChanged: {
|
||||
if(jsChart) {
|
||||
jsChart.resize();
|
||||
if(d.jsChart) {
|
||||
d.jsChart.resize();
|
||||
}
|
||||
}
|
||||
onHeightChanged: {
|
||||
if(jsChart) {
|
||||
jsChart.resize();
|
||||
if(d.jsChart) {
|
||||
d.jsChart.resize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
18
src/Qt5/imports/FluentUI/Controls/FluImageButton.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
@ -3,10 +3,10 @@ import QtQuick.Window 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import FluentUI 1.0
|
||||
import org.wangwenx190.FramelessHelper 1.0
|
||||
|
||||
Window {
|
||||
default property alias content: container.data
|
||||
default property alias content: layout_content.data
|
||||
property string windowIcon: FluApp.windowIcon
|
||||
property bool closeDestory: true
|
||||
property int launchMode: FluWindowType.Standard
|
||||
property var argument:({})
|
||||
@ -16,13 +16,13 @@ Window {
|
||||
property bool fitsAppBarWindows: false
|
||||
property Item appBar: FluAppBar {
|
||||
title: window.title
|
||||
width: window.width
|
||||
height: 30
|
||||
showDark: window.showDark
|
||||
showClose: window.showClose
|
||||
showMinimize: window.showMinimize
|
||||
showMaximize: window.showMaximize
|
||||
showStayTop: window.showStayTop
|
||||
icon: window.windowIcon
|
||||
}
|
||||
property color backgroundColor: {
|
||||
if(active){
|
||||
@ -38,8 +38,10 @@ Window {
|
||||
property bool showMinimize: true
|
||||
property bool showMaximize: true
|
||||
property bool showStayTop: true
|
||||
property bool useSystemAppBar
|
||||
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){
|
||||
if(closeDestory){
|
||||
destoryOnClose()
|
||||
@ -51,26 +53,23 @@ Window {
|
||||
signal initArgument(var argument)
|
||||
signal firstVisible()
|
||||
id:window
|
||||
maximumWidth: useSystemAppBar&&fixSize ? width : 16777215
|
||||
maximumHeight: useSystemAppBar&&fixSize ? height : 16777215
|
||||
minimumWidth: useSystemAppBar&&fixSize ? width : 0
|
||||
minimumHeight: useSystemAppBar&&fixSize ? height : 0
|
||||
maximumWidth: fixSize ? width : 16777215
|
||||
maximumHeight: fixSize ? height : 16777215
|
||||
minimumWidth: fixSize ? width : 0
|
||||
minimumHeight: fixSize ? height : 0
|
||||
color:"transparent"
|
||||
onStayTopChanged: {
|
||||
d.changedStayTop()
|
||||
}
|
||||
Component.onCompleted: {
|
||||
useSystemAppBar = FluApp.useSystemAppBar
|
||||
if(!useSystemAppBar){
|
||||
loader_frameless.sourceComponent = com_frameless
|
||||
}
|
||||
lifecycle.onCompleted(window)
|
||||
initArgument(argument)
|
||||
d.changedStayTop()
|
||||
if(useSystemAppBar){
|
||||
window.moveWindowToDesktopCenter()
|
||||
if(window.autoMaximize){
|
||||
window.showMaximized()
|
||||
}else{
|
||||
window.show()
|
||||
}
|
||||
moveWindowToDesktopCenter()
|
||||
if(window.autoMaximize){
|
||||
window.showMaximized()
|
||||
}else{
|
||||
window.show()
|
||||
}
|
||||
}
|
||||
Component.onDestruction: {
|
||||
@ -86,74 +85,27 @@ Window {
|
||||
QtObject{
|
||||
id:d
|
||||
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{
|
||||
target: window
|
||||
function onClosing(event){closeListener(event)}
|
||||
}
|
||||
Component{
|
||||
id:com_frameless
|
||||
FluFramelessHelper{}
|
||||
}
|
||||
Component{
|
||||
id:com_background
|
||||
Rectangle{
|
||||
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{
|
||||
id:com_app_bar
|
||||
Item{
|
||||
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{
|
||||
id:com_loading
|
||||
Popup{
|
||||
@ -216,65 +168,95 @@ Window {
|
||||
}
|
||||
}
|
||||
}
|
||||
FluInfoBar{
|
||||
id:infoBar
|
||||
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{
|
||||
id:lifecycle
|
||||
}
|
||||
FluLoader{
|
||||
id:loader_window_border
|
||||
anchors.fill: parent
|
||||
z:999
|
||||
sourceComponent: FluApp.useSystemAppBar ? undefined : com_window_border
|
||||
id:loader_frameless
|
||||
}
|
||||
Component{
|
||||
id:com_window_border
|
||||
Item{
|
||||
WindowBorder{
|
||||
anchors.fill: parent
|
||||
visible: !FluTools.isLinux()
|
||||
}
|
||||
Rectangle{
|
||||
anchors.fill: parent
|
||||
color: Qt.rgba(0,0,0,0)
|
||||
border.width: 1
|
||||
visible: FluTools.isLinux()
|
||||
border.color: {
|
||||
if(window.active){
|
||||
return Qt.rgba(51/255,51/255,51/255,1)
|
||||
}
|
||||
return Qt.rgba(153/255,153/255,153/255,1)
|
||||
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{
|
||||
id:infoBar
|
||||
root: window
|
||||
}
|
||||
WindowLifecycle{
|
||||
id:lifecycle
|
||||
}
|
||||
Rectangle{
|
||||
anchors.fill: parent
|
||||
color:"transparent"
|
||||
border.width: window.resizeBorderWidth
|
||||
border.color: window.resizeBorderColor
|
||||
visible: {
|
||||
if(window.useSystemAppBar){
|
||||
return false
|
||||
}
|
||||
if(window.visibility == Window.Maximized || window.visibility == Window.FullScreen){
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
function destoryOnClose(){
|
||||
@ -304,14 +286,17 @@ Window {
|
||||
return lifecycle.createRegister(window,path)
|
||||
}
|
||||
function moveWindowToDesktopCenter(){
|
||||
return framless_helper.moveWindowToDesktopCenter()
|
||||
window.setGeometry((Screen.width-window.width)/2+Screen.virtualX,(Screen.height-window.height)/2+Screen.virtualY,window.width,window.height)
|
||||
}
|
||||
function onResult(data){
|
||||
if(_pageRegister){
|
||||
_pageRegister.onResult(data)
|
||||
}
|
||||
}
|
||||
function containerItem(){
|
||||
return container
|
||||
function layoutContainer(){
|
||||
return layout_container
|
||||
}
|
||||
function layoutContent(){
|
||||
return layout_content
|
||||
}
|
||||
}
|
||||
|
BIN
src/Qt5/imports/FluentUI/Image/btn_close_hovered.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/Qt5/imports/FluentUI/Image/btn_close_normal.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
src/Qt5/imports/FluentUI/Image/btn_close_pushed.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/Qt5/imports/FluentUI/Image/btn_max_hovered.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/Qt5/imports/FluentUI/Image/btn_max_normal.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
src/Qt5/imports/FluentUI/Image/btn_max_pushed.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/Qt5/imports/FluentUI/Image/btn_min_hovered.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
src/Qt5/imports/FluentUI/Image/btn_min_normal.png
Normal file
After Width: | Height: | Size: 9.8 KiB |
BIN
src/Qt5/imports/FluentUI/Image/btn_min_pushed.png
Normal file
After Width: | Height: | Size: 10 KiB |
25645
src/Qt5/imports/FluentUI/JS/Chart.js
vendored
@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
|
||||
// It is used for QML tooling purposes only.
|
||||
//
|
||||
// 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 {
|
||||
dependencies: ["QtQuick 2.0"]
|
||||
@ -75,6 +75,12 @@ Module {
|
||||
Parameter { name: "data"; type: "QVariantMap" }
|
||||
}
|
||||
}
|
||||
Component {
|
||||
name: "FluFramelessHelper"
|
||||
prototype: "QObject"
|
||||
exports: ["FluentUI/FluFramelessHelper 1.0"]
|
||||
exportMetaObjectRevisions: [0]
|
||||
}
|
||||
Component {
|
||||
name: "FluNavigationViewType"
|
||||
exports: ["FluentUI/FluNavigationViewType 1.0"]
|
||||
@ -1866,6 +1872,11 @@ Module {
|
||||
type: "NetworkParams*"
|
||||
Parameter { name: "target"; type: "QObject"; isPointer: true }
|
||||
}
|
||||
Method {
|
||||
name: "openLog"
|
||||
type: "NetworkParams*"
|
||||
Parameter { name: "val"; type: "QVariant" }
|
||||
}
|
||||
Method {
|
||||
name: "go"
|
||||
Parameter { name: "result"; type: "NetworkCallable"; isPointer: true }
|
||||
@ -2538,17 +2549,12 @@ Module {
|
||||
exportMetaObjectRevisions: [0]
|
||||
isComposite: true
|
||||
defaultProperty: "data"
|
||||
Property { name: "window"; type: "QVariant" }
|
||||
Property { name: "jsChart"; type: "QVariant" }
|
||||
Property { name: "chartType"; type: "string" }
|
||||
Property { name: "chartData"; type: "QVariant" }
|
||||
Property { name: "chartOptions"; type: "QVariant" }
|
||||
Property { name: "chartAnimationProgress"; type: "double" }
|
||||
Property { name: "animationEasingType"; type: "int" }
|
||||
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" }
|
||||
Signal { name: "animationFinished" }
|
||||
Method { name: "animateToNewData"; type: "QVariant" }
|
||||
@ -2649,9 +2655,13 @@ Module {
|
||||
Property { name: "neutralText"; type: "string" }
|
||||
Property { name: "negativeText"; type: "string" }
|
||||
Property { name: "positiveText"; type: "string" }
|
||||
Property { name: "messageTextFormart"; type: "int" }
|
||||
Property { name: "delayTime"; 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: "negativeClicked" }
|
||||
Signal { name: "positiveClicked" }
|
||||
@ -3003,15 +3013,15 @@ Module {
|
||||
defaultProperty: "data"
|
||||
Property { name: "logo"; type: "QUrl" }
|
||||
Property { name: "title"; type: "string" }
|
||||
Property { name: "items"; type: "FluObject_QMLTYPE_124"; isPointer: true }
|
||||
Property { name: "footerItems"; type: "FluObject_QMLTYPE_124"; isPointer: true }
|
||||
Property { name: "items"; type: "FluObject_QMLTYPE_125"; isPointer: true }
|
||||
Property { name: "footerItems"; type: "FluObject_QMLTYPE_125"; isPointer: true }
|
||||
Property { name: "displayMode"; type: "int" }
|
||||
Property { name: "autoSuggestBox"; type: "QQmlComponent"; isPointer: true }
|
||||
Property { name: "actionItem"; type: "QQmlComponent"; isPointer: true }
|
||||
Property { name: "topPadding"; type: "int" }
|
||||
Property { name: "pageMode"; type: "int" }
|
||||
Property { name: "navItemRightMenu"; type: "FluMenu_QMLTYPE_39"; isPointer: true }
|
||||
Property { name: "navItemExpanderRightMenu"; type: "FluMenu_QMLTYPE_39"; isPointer: true }
|
||||
Property { name: "navItemRightMenu"; type: "FluMenu_QMLTYPE_34"; isPointer: true }
|
||||
Property { name: "navItemExpanderRightMenu"; type: "FluMenu_QMLTYPE_34"; isPointer: true }
|
||||
Property { name: "navCompactWidth"; type: "int" }
|
||||
Property { name: "navTopMargin"; type: "int" }
|
||||
Property { name: "cellHeight"; type: "int" }
|
||||
@ -3758,6 +3768,91 @@ Module {
|
||||
Method { name: "allExpand"; 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 {
|
||||
prototype: "QQuickRow"
|
||||
name: "FluentUI/NumberBox 1.0"
|
||||
|
@ -97,5 +97,15 @@
|
||||
<file>FluentUI/Controls/FluClip.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>
|
||||
</RCC>
|
||||
|
@ -34,10 +34,17 @@ Rectangle{
|
||||
property bool isMac: FluTools.isMacos()
|
||||
property color borerlessColor : FluTheme.primaryColor
|
||||
property var maxClickListener : function(){
|
||||
if (d.win.visibility === Window.Maximized)
|
||||
d.win.visibility = Window.Windowed
|
||||
else
|
||||
d.win.visibility = Window.Maximized
|
||||
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)
|
||||
d.win.visibility = Window.Windowed
|
||||
else
|
||||
d.win.visibility = Window.Maximized
|
||||
}
|
||||
}
|
||||
property var minClickListener: function(){
|
||||
d.win.visibility = Window.Minimized
|
||||
@ -74,14 +81,16 @@ Rectangle{
|
||||
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)
|
||||
}
|
||||
TapHandler {
|
||||
onTapped: if (tapCount === 2 && d.resizable) btn_maximize.clicked()
|
||||
gesturePolicy: TapHandler.DragThreshold
|
||||
}
|
||||
DragHandler {
|
||||
target: null
|
||||
grabPermissions: TapHandler.CanTakeOverFromAnything
|
||||
onActiveChanged: if (active) { d.win.startSystemMove(); }
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onPositionChanged: {
|
||||
d.win.startSystemMove()
|
||||
}
|
||||
onDoubleClicked: {
|
||||
if(d.resizable){
|
||||
btn_maximize.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
Row{
|
||||
anchors{
|
||||
@ -105,6 +114,49 @@ Rectangle{
|
||||
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{
|
||||
anchors.right: parent.right
|
||||
height: control.height
|
||||
|
@ -3,25 +3,27 @@ import "./../JS/Chart.js" as Chart
|
||||
|
||||
Canvas {
|
||||
id: control
|
||||
property var window: Window.window
|
||||
property var jsChart: undefined
|
||||
property string chartType
|
||||
property var chartData
|
||||
property var chartOptions
|
||||
property double chartAnimationProgress: 0.1
|
||||
property int animationEasingType: Easing.InOutExpo
|
||||
property double animationDuration: 0
|
||||
property var memorizedContext
|
||||
property var memorizedData
|
||||
property var memorizedOptions
|
||||
property double animationDuration: 300
|
||||
property alias animationRunning: chartAnimator.running
|
||||
signal animationFinished()
|
||||
function animateToNewData()
|
||||
{
|
||||
chartAnimationProgress = 0.1;
|
||||
jsChart.update();
|
||||
d.jsChart.update();
|
||||
chartAnimator.restart();
|
||||
}
|
||||
QtObject{
|
||||
id:d
|
||||
property var jsChart: undefined
|
||||
property var memorizedContext
|
||||
property var memorizedData
|
||||
property var memorizedOptions
|
||||
}
|
||||
MouseArea {
|
||||
id: event
|
||||
anchors.fill: control
|
||||
@ -47,31 +49,33 @@ Canvas {
|
||||
mouseEvent.left = 0;
|
||||
mouseEvent.top = 0;
|
||||
mouseEvent.target = control;
|
||||
|
||||
if(handler) {
|
||||
handler(mouseEvent);
|
||||
}
|
||||
|
||||
control.requestPaint();
|
||||
}
|
||||
onClicked:(mouse)=> {
|
||||
submitEvent(mouse, "click");
|
||||
}
|
||||
onPositionChanged:(mouse)=> {
|
||||
submitEvent(mouse, "mousemove");
|
||||
}
|
||||
onClicked:
|
||||
(mouse)=> {
|
||||
submitEvent(mouse, "click");
|
||||
}
|
||||
onPositionChanged:
|
||||
(mouse)=> {
|
||||
submitEvent(mouse, "mousemove");
|
||||
}
|
||||
onExited: {
|
||||
submitEvent(undefined, "mouseout");
|
||||
}
|
||||
onEntered: {
|
||||
submitEvent(undefined, "mouseenter");
|
||||
}
|
||||
onPressed:(mouse)=> {
|
||||
submitEvent(mouse, "mousedown");
|
||||
}
|
||||
onReleased:(mouse)=> {
|
||||
submitEvent(mouse, "mouseup");
|
||||
}
|
||||
onPressed:
|
||||
(mouse)=> {
|
||||
submitEvent(mouse, "mousedown");
|
||||
}
|
||||
onReleased:
|
||||
(mouse)=> {
|
||||
submitEvent(mouse, "mouseup");
|
||||
}
|
||||
}
|
||||
PropertyAnimation {
|
||||
id: chartAnimator
|
||||
@ -89,34 +93,25 @@ Canvas {
|
||||
control.requestPaint();
|
||||
}
|
||||
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');
|
||||
|
||||
jsChart = Chart.build(ctx, {
|
||||
type: control.chartType,
|
||||
data: control.chartData,
|
||||
options: control.chartOptions
|
||||
});
|
||||
|
||||
memorizedData = control.chartData ;
|
||||
memorizedContext = control.getContext('2d');
|
||||
memorizedOptions = control.chartOptions;
|
||||
|
||||
control.jsChart.bindEvents(function(newHandler) {event.handler = newHandler;});
|
||||
|
||||
d.jsChart = Chart.build(ctx, {type: control.chartType,data: control.chartData,options: control.chartOptions});
|
||||
d.memorizedData = control.chartData ;
|
||||
d.memorizedContext = control.getContext('2d');
|
||||
d.memorizedOptions = control.chartOptions;
|
||||
d.jsChart.bindEvents(function(newHandler) {event.handler = newHandler;});
|
||||
chartAnimator.start();
|
||||
}
|
||||
|
||||
jsChart.draw(chartAnimationProgress);
|
||||
d.jsChart.draw(chartAnimationProgress);
|
||||
}
|
||||
onWidthChanged: {
|
||||
if(jsChart) {
|
||||
jsChart.resize();
|
||||
if(d.jsChart) {
|
||||
d.jsChart.resize();
|
||||
}
|
||||
}
|
||||
onHeightChanged: {
|
||||
if(jsChart) {
|
||||
jsChart.resize();
|
||||
if(d.jsChart) {
|
||||
d.jsChart.resize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
18
src/Qt6/imports/FluentUI/Controls/FluImageButton.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
@ -2,10 +2,10 @@ import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import FluentUI
|
||||
import org.wangwenx190.FramelessHelper
|
||||
|
||||
Window {
|
||||
default property alias content: container.data
|
||||
default property alias content: layout_content.data
|
||||
property string windowIcon: FluApp.windowIcon
|
||||
property bool closeDestory: true
|
||||
property int launchMode: FluWindowType.Standard
|
||||
property var argument:({})
|
||||
@ -15,13 +15,13 @@ Window {
|
||||
property bool fitsAppBarWindows: false
|
||||
property Item appBar: FluAppBar {
|
||||
title: window.title
|
||||
width: window.width
|
||||
height: 30
|
||||
showDark: window.showDark
|
||||
showClose: window.showClose
|
||||
showMinimize: window.showMinimize
|
||||
showMaximize: window.showMaximize
|
||||
showStayTop: window.showStayTop
|
||||
icon: window.windowIcon
|
||||
}
|
||||
property color backgroundColor: {
|
||||
if(active){
|
||||
@ -37,8 +37,10 @@ Window {
|
||||
property bool showMinimize: true
|
||||
property bool showMaximize: true
|
||||
property bool showStayTop: true
|
||||
property bool useSystemAppBar
|
||||
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){
|
||||
if(closeDestory){
|
||||
destoryOnClose()
|
||||
@ -50,26 +52,23 @@ Window {
|
||||
signal initArgument(var argument)
|
||||
signal firstVisible()
|
||||
id:window
|
||||
maximumWidth: useSystemAppBar&&fixSize ? width : 16777215
|
||||
maximumHeight: useSystemAppBar&&fixSize ? height : 16777215
|
||||
minimumWidth: useSystemAppBar&&fixSize ? width : 0
|
||||
minimumHeight: useSystemAppBar&&fixSize ? height : 0
|
||||
maximumWidth: fixSize ? width : 16777215
|
||||
maximumHeight: fixSize ? height : 16777215
|
||||
minimumWidth: fixSize ? width : 0
|
||||
minimumHeight: fixSize ? height : 0
|
||||
color:"transparent"
|
||||
onStayTopChanged: {
|
||||
d.changedStayTop()
|
||||
}
|
||||
Component.onCompleted: {
|
||||
useSystemAppBar = FluApp.useSystemAppBar
|
||||
if(!useSystemAppBar){
|
||||
loader_frameless.sourceComponent = com_frameless
|
||||
}
|
||||
lifecycle.onCompleted(window)
|
||||
initArgument(argument)
|
||||
d.changedStayTop()
|
||||
if(useSystemAppBar){
|
||||
window.moveWindowToDesktopCenter()
|
||||
if(window.autoMaximize){
|
||||
window.showMaximized()
|
||||
}else{
|
||||
window.show()
|
||||
}
|
||||
moveWindowToDesktopCenter()
|
||||
if(window.autoMaximize){
|
||||
window.showMaximized()
|
||||
}else{
|
||||
window.show()
|
||||
}
|
||||
}
|
||||
Component.onDestruction: {
|
||||
@ -85,74 +84,27 @@ Window {
|
||||
QtObject{
|
||||
id:d
|
||||
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{
|
||||
target: window
|
||||
function onClosing(event){closeListener(event)}
|
||||
}
|
||||
Component{
|
||||
id:com_frameless
|
||||
FluFramelessHelper{}
|
||||
}
|
||||
Component{
|
||||
id:com_background
|
||||
Rectangle{
|
||||
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{
|
||||
id:com_app_bar
|
||||
Item{
|
||||
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{
|
||||
id:com_loading
|
||||
Popup{
|
||||
@ -215,65 +167,95 @@ Window {
|
||||
}
|
||||
}
|
||||
}
|
||||
FluInfoBar{
|
||||
id:infoBar
|
||||
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{
|
||||
id:lifecycle
|
||||
}
|
||||
FluLoader{
|
||||
id:loader_window_border
|
||||
anchors.fill: parent
|
||||
z:999
|
||||
sourceComponent: FluApp.useSystemAppBar ? undefined : com_window_border
|
||||
id:loader_frameless
|
||||
}
|
||||
Component{
|
||||
id:com_window_border
|
||||
Item{
|
||||
WindowBorder{
|
||||
anchors.fill: parent
|
||||
visible: !FluTools.isLinux()
|
||||
}
|
||||
Rectangle{
|
||||
anchors.fill: parent
|
||||
color: Qt.rgba(0,0,0,0)
|
||||
border.width: 1
|
||||
visible: FluTools.isLinux()
|
||||
border.color: {
|
||||
if(window.active){
|
||||
return Qt.rgba(51/255,51/255,51/255,1)
|
||||
}
|
||||
return Qt.rgba(153/255,153/255,153/255,1)
|
||||
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{
|
||||
id:infoBar
|
||||
root: window
|
||||
}
|
||||
WindowLifecycle{
|
||||
id:lifecycle
|
||||
}
|
||||
Rectangle{
|
||||
anchors.fill: parent
|
||||
color:"transparent"
|
||||
border.width: window.resizeBorderWidth
|
||||
border.color: window.resizeBorderColor
|
||||
visible: {
|
||||
if(window.useSystemAppBar){
|
||||
return false
|
||||
}
|
||||
if(window.visibility == Window.Maximized || window.visibility == Window.FullScreen){
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
function destoryOnClose(){
|
||||
@ -303,14 +285,17 @@ Window {
|
||||
return lifecycle.createRegister(window,path)
|
||||
}
|
||||
function moveWindowToDesktopCenter(){
|
||||
return framless_helper.moveWindowToDesktopCenter()
|
||||
window.setGeometry((Screen.width-window.width)/2+Screen.virtualX,(Screen.height-window.height)/2+Screen.virtualY,window.width,window.height)
|
||||
}
|
||||
function onResult(data){
|
||||
if(_pageRegister){
|
||||
_pageRegister.onResult(data)
|
||||
}
|
||||
}
|
||||
function containerItem(){
|
||||
return container
|
||||
function layoutContainer(){
|
||||
return layout_container
|
||||
}
|
||||
function layoutContent(){
|
||||
return layout_content
|
||||
}
|
||||
}
|
||||
|
BIN
src/Qt6/imports/FluentUI/Image/btn_close_hovered.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/Qt6/imports/FluentUI/Image/btn_close_normal.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
src/Qt6/imports/FluentUI/Image/btn_close_pushed.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/Qt6/imports/FluentUI/Image/btn_max_hovered.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/Qt6/imports/FluentUI/Image/btn_max_normal.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
src/Qt6/imports/FluentUI/Image/btn_max_pushed.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/Qt6/imports/FluentUI/Image/btn_min_hovered.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
src/Qt6/imports/FluentUI/Image/btn_min_normal.png
Normal file
After Width: | Height: | Size: 9.8 KiB |
BIN
src/Qt6/imports/FluentUI/Image/btn_min_pushed.png
Normal file
After Width: | Height: | Size: 10 KiB |
25645
src/Qt6/imports/FluentUI/JS/Chart.js
vendored
@ -8,7 +8,6 @@ WindowLifecycle::WindowLifecycle(QObject *parent):QObject{parent}{
|
||||
|
||||
void WindowLifecycle::onCompleted(QQuickWindow* window){
|
||||
this->_window = window;
|
||||
vsyncEnable(FluApp::getInstance()->vsync());
|
||||
FluApp::getInstance()->addWindow(this->_window);
|
||||
}
|
||||
|
||||
@ -22,12 +21,6 @@ void WindowLifecycle::onDestruction(){
|
||||
void WindowLifecycle::onVisible(bool visible){
|
||||
}
|
||||
|
||||
void WindowLifecycle::vsyncEnable(bool enable){
|
||||
auto froamt = _window->format();
|
||||
froamt.setSwapInterval(enable);
|
||||
_window->setFormat(froamt);
|
||||
}
|
||||
|
||||
QVariant WindowLifecycle::createRegister(QQuickWindow* window,const QString& path){
|
||||
FluRegister *p = new FluRegister(window);
|
||||
p->from(window);
|
||||
|
@ -22,7 +22,6 @@ public:
|
||||
Q_INVOKABLE void onVisible(bool visible);
|
||||
Q_INVOKABLE void onDestoryOnClose();
|
||||
Q_INVOKABLE QVariant createRegister(QQuickWindow* window,const QString& path);
|
||||
void vsyncEnable(bool enable);
|
||||
private:
|
||||
QQuickWindow* _window;
|
||||
};
|
||||
|
231
src/qrcode/bitstream.cpp
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Binary sequence class.
|
||||
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bitstream.h"
|
||||
|
||||
#define DEFAULT_BUFSIZE (128)
|
||||
|
||||
BitStream *BitStream_new(void)
|
||||
{
|
||||
BitStream *bstream;
|
||||
|
||||
bstream = (BitStream *)malloc(sizeof(BitStream));
|
||||
if(bstream == NULL) return NULL;
|
||||
|
||||
bstream->length = 0;
|
||||
bstream->data = (unsigned char *)malloc(DEFAULT_BUFSIZE);
|
||||
if(bstream->data == NULL) {
|
||||
free(bstream);
|
||||
return NULL;
|
||||
}
|
||||
bstream->datasize = DEFAULT_BUFSIZE;
|
||||
|
||||
return bstream;
|
||||
}
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
BitStream *BitStream_newWithBits(size_t size, unsigned char *bits)
|
||||
{
|
||||
BitStream *bstream;
|
||||
|
||||
if(size == 0) return BitStream_new();
|
||||
|
||||
bstream = (BitStream *)malloc(sizeof(BitStream));
|
||||
if(bstream == NULL) return NULL;
|
||||
|
||||
bstream->data = (unsigned char *)malloc(size);
|
||||
if(bstream->data == NULL) {
|
||||
free(bstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bstream->length = size;
|
||||
bstream->datasize = size;
|
||||
memcpy(bstream->data, bits, size);
|
||||
|
||||
return bstream;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int BitStream_expand(BitStream *bstream)
|
||||
{
|
||||
unsigned char *data;
|
||||
|
||||
data = (unsigned char *)realloc(bstream->data, bstream->datasize * 2);
|
||||
if(data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bstream->data = data;
|
||||
bstream->datasize *= 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void BitStream_writeNum(unsigned char *dest, size_t bits, unsigned int num)
|
||||
{
|
||||
unsigned int mask;
|
||||
size_t i;
|
||||
unsigned char *p;
|
||||
|
||||
p = dest;
|
||||
mask = 1U << (bits - 1);
|
||||
for(i = 0; i < bits; i++) {
|
||||
if(num & mask) {
|
||||
*p = 1;
|
||||
} else {
|
||||
*p = 0;
|
||||
}
|
||||
p++;
|
||||
mask = mask >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void BitStream_writeBytes(unsigned char *dest, size_t size, unsigned char *data)
|
||||
{
|
||||
unsigned char mask;
|
||||
size_t i, j;
|
||||
unsigned char *p;
|
||||
|
||||
p = dest;
|
||||
for(i = 0; i < size; i++) {
|
||||
mask = 0x80;
|
||||
for(j = 0; j < 8; j++) {
|
||||
if(data[i] & mask) {
|
||||
*p = 1;
|
||||
} else {
|
||||
*p = 0;
|
||||
}
|
||||
p++;
|
||||
mask = mask >> 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int BitStream_append(BitStream *bstream, BitStream *arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if(arg == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if(arg->length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while(bstream->length + arg->length > bstream->datasize) {
|
||||
ret = BitStream_expand(bstream);
|
||||
if(ret < 0) return ret;
|
||||
}
|
||||
|
||||
memcpy(bstream->data + bstream->length, arg->data, arg->length);
|
||||
bstream->length += arg->length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if(bits == 0) return 0;
|
||||
|
||||
while(bstream->datasize - bstream->length < bits) {
|
||||
ret = BitStream_expand(bstream);
|
||||
if(ret < 0) return ret;
|
||||
}
|
||||
BitStream_writeNum(bstream->data + bstream->length, bits, num);
|
||||
bstream->length += bits;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BitStream_appendBytes(BitStream *bstream, size_t size, unsigned char *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if(size == 0) return 0;
|
||||
|
||||
while(bstream->datasize - bstream->length < size * 8) {
|
||||
ret = BitStream_expand(bstream);
|
||||
if(ret < 0) return ret;
|
||||
}
|
||||
BitStream_writeBytes(bstream->data + bstream->length, size, data);
|
||||
bstream->length += size * 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char *BitStream_toByte(BitStream *bstream)
|
||||
{
|
||||
size_t i, j, size, bytes, oddbits;
|
||||
unsigned char *data, v;
|
||||
unsigned char *p;
|
||||
|
||||
size = BitStream_size(bstream);
|
||||
if(size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
data = (unsigned char *)malloc((size + 7) / 8);
|
||||
if(data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bytes = size / 8;
|
||||
|
||||
p = bstream->data;
|
||||
for(i = 0; i < bytes; i++) {
|
||||
v = 0;
|
||||
for(j = 0; j < 8; j++) {
|
||||
v = (unsigned char)(v << 1);
|
||||
v |= *p;
|
||||
p++;
|
||||
}
|
||||
data[i] = v;
|
||||
}
|
||||
oddbits = size & 7;
|
||||
if(oddbits > 0) {
|
||||
v = 0;
|
||||
for(j = 0; j < oddbits; j++) {
|
||||
v = (unsigned char)(v << 1);
|
||||
v |= *p;
|
||||
p++;
|
||||
}
|
||||
data[bytes] = (unsigned char)(v << (8 - oddbits));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void BitStream_free(BitStream *bstream)
|
||||
{
|
||||
if(bstream != NULL) {
|
||||
free(bstream->data);
|
||||
free(bstream);
|
||||
}
|
||||
}
|
43
src/qrcode/bitstream.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Binary sequence class.
|
||||
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef BITSTREAM_H
|
||||
#define BITSTREAM_H
|
||||
|
||||
typedef struct {
|
||||
size_t length;
|
||||
size_t datasize;
|
||||
unsigned char *data;
|
||||
} BitStream;
|
||||
|
||||
extern BitStream *BitStream_new(void);
|
||||
#ifdef WITH_TESTS
|
||||
extern BitStream *BitStream_newWithBits(size_t size, unsigned char *bits);
|
||||
#endif
|
||||
extern int BitStream_append(BitStream *bstream, BitStream *arg);
|
||||
extern int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num);
|
||||
extern int BitStream_appendBytes(BitStream *bstream, size_t size, unsigned char *data);
|
||||
#define BitStream_size(__bstream__) (__bstream__->length)
|
||||
#define BitStream_reset(__bstream__) (__bstream__->length = 0)
|
||||
extern unsigned char *BitStream_toByte(BitStream *bstream);
|
||||
extern void BitStream_free(BitStream *bstream);
|
||||
|
||||
#endif /* BITSTREAM_H */
|
99
src/qrcode/config.h
Normal file
@ -0,0 +1,99 @@
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define if you have the iconv() function and it works. */
|
||||
/* #undef HAVE_ICONV */
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if using pthread is enabled. */
|
||||
#define HAVE_LIBPTHREAD 0
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if using libpng is enabled. */
|
||||
#define HAVE_PNG 0
|
||||
|
||||
/* Define to 1 if using SDL is enabled. */
|
||||
/* #undef HAVE_SDL */
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the `strdup' function. */
|
||||
#define HAVE_STRDUP 0
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* Major version number */
|
||||
#define MAJOR_VERSION 4
|
||||
|
||||
/* Micro version number */
|
||||
#define MICRO_VERSION 2
|
||||
|
||||
/* Minor version number */
|
||||
#define MINOR_VERSION 0
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "qrencode"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "QRencode"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "QRencode 4.0.2"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "qrencode"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "4.0.2"
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "4.0.2"
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
/* #undef inline */
|
||||
#endif
|
||||
|
||||
/* Define to 'static' if no test programs will be compiled. */
|
||||
#define STATIC_IN_RELEASE static
|
||||
/* #undef WITH_TESTS */
|
357
src/qrcode/mask.cpp
Normal file
@ -0,0 +1,357 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Masking.
|
||||
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "qrencode.h"
|
||||
#include "qrspec.h"
|
||||
#include "mask.h"
|
||||
|
||||
STATIC_IN_RELEASE int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level)
|
||||
{
|
||||
unsigned int format;
|
||||
unsigned char v;
|
||||
int i;
|
||||
int blacks = 0;
|
||||
|
||||
format = QRspec_getFormatInfo(mask, level);
|
||||
|
||||
for(i = 0; i < 8; i++) {
|
||||
if(format & 1) {
|
||||
blacks += 2;
|
||||
v = 0x85;
|
||||
} else {
|
||||
v = 0x84;
|
||||
}
|
||||
frame[width * 8 + width - 1 - i] = v;
|
||||
if(i < 6) {
|
||||
frame[width * i + 8] = v;
|
||||
} else {
|
||||
frame[width * (i + 1) + 8] = v;
|
||||
}
|
||||
format= format >> 1;
|
||||
}
|
||||
for(i = 0; i < 7; i++) {
|
||||
if(format & 1) {
|
||||
blacks += 2;
|
||||
v = 0x85;
|
||||
} else {
|
||||
v = 0x84;
|
||||
}
|
||||
frame[width * (width - 7 + i) + 8] = v;
|
||||
if(i == 0) {
|
||||
frame[width * 8 + 7] = v;
|
||||
} else {
|
||||
frame[width * 8 + 6 - i] = v;
|
||||
}
|
||||
format= format >> 1;
|
||||
}
|
||||
|
||||
return blacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Demerit coefficients.
|
||||
* See Section 8.8.2, pp.45, JIS X0510:2004.
|
||||
*/
|
||||
#define N1 (3)
|
||||
#define N2 (3)
|
||||
#define N3 (40)
|
||||
#define N4 (10)
|
||||
|
||||
#define MASKMAKER(__exp__) \
|
||||
int x, y;\
|
||||
int b = 0;\
|
||||
\
|
||||
for(y = 0; y < width; y++) {\
|
||||
for(x = 0; x < width; x++) {\
|
||||
if(*s & 0x80) {\
|
||||
*d = *s;\
|
||||
} else {\
|
||||
*d = *s ^ ((__exp__) == 0);\
|
||||
}\
|
||||
b += (int)(*d & 1);\
|
||||
s++; d++;\
|
||||
}\
|
||||
}\
|
||||
return b;
|
||||
|
||||
static int Mask_mask0(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER((x+y)&1)
|
||||
}
|
||||
|
||||
static int Mask_mask1(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER(y&1)
|
||||
}
|
||||
|
||||
static int Mask_mask2(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER(x%3)
|
||||
}
|
||||
|
||||
static int Mask_mask3(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER((x+y)%3)
|
||||
}
|
||||
|
||||
static int Mask_mask4(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER(((y/2)+(x/3))&1)
|
||||
}
|
||||
|
||||
static int Mask_mask5(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER(((x*y)&1)+(x*y)%3)
|
||||
}
|
||||
|
||||
static int Mask_mask6(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER((((x*y)&1)+(x*y)%3)&1)
|
||||
}
|
||||
|
||||
static int Mask_mask7(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER((((x*y)%3)+((x+y)&1))&1)
|
||||
}
|
||||
|
||||
#define maskNum (8)
|
||||
typedef int MaskMaker(int, const unsigned char *, unsigned char *);
|
||||
static MaskMaker *maskMakers[maskNum] = {
|
||||
Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3,
|
||||
Mask_mask4, Mask_mask5, Mask_mask6, Mask_mask7
|
||||
};
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask)
|
||||
{
|
||||
unsigned char *masked;
|
||||
|
||||
masked = (unsigned char *)malloc((size_t)(width * width));
|
||||
if(masked == NULL) return NULL;
|
||||
|
||||
maskMakers[mask](width, frame, masked);
|
||||
|
||||
return masked;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level)
|
||||
{
|
||||
unsigned char *masked;
|
||||
|
||||
if(mask < 0 || mask >= maskNum) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
masked = (unsigned char *)malloc((size_t)(width * width));
|
||||
if(masked == NULL) return NULL;
|
||||
|
||||
maskMakers[mask](width, frame, masked);
|
||||
Mask_writeFormatInformation(width, masked, mask, level);
|
||||
|
||||
return masked;
|
||||
}
|
||||
|
||||
|
||||
//static int n1;
|
||||
//static int n2;
|
||||
//static int n3;
|
||||
//static int n4;
|
||||
|
||||
STATIC_IN_RELEASE int Mask_calcN1N3(int length, int *runLength)
|
||||
{
|
||||
int i;
|
||||
int demerit = 0;
|
||||
int fact;
|
||||
|
||||
for(i = 0; i < length; i++) {
|
||||
if(runLength[i] >= 5) {
|
||||
demerit += N1 + (runLength[i] - 5);
|
||||
//n1 += N1 + (runLength[i] - 5);
|
||||
}
|
||||
if((i & 1)) {
|
||||
if(i >= 3 && i < length-2 && (runLength[i] % 3) == 0) {
|
||||
fact = runLength[i] / 3;
|
||||
if(runLength[i-2] == fact &&
|
||||
runLength[i-1] == fact &&
|
||||
runLength[i+1] == fact &&
|
||||
runLength[i+2] == fact) {
|
||||
if(i == 3 || runLength[i-3] >= 4 * fact) {
|
||||
demerit += N3;
|
||||
//n3 += N3;
|
||||
} else if(i+4 >= length || runLength[i+3] >= 4 * fact) {
|
||||
demerit += N3;
|
||||
//n3 += N3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return demerit;
|
||||
}
|
||||
|
||||
STATIC_IN_RELEASE int Mask_calcN2(int width, unsigned char *frame)
|
||||
{
|
||||
int x, y;
|
||||
unsigned char *p;
|
||||
unsigned char b22, w22;
|
||||
int demerit = 0;
|
||||
|
||||
p = frame + width + 1;
|
||||
for(y = 1; y < width; y++) {
|
||||
for(x = 1; x < width; x++) {
|
||||
b22 = p[0] & p[-1] & p[-width] & p [-width-1];
|
||||
w22 = p[0] | p[-1] | p[-width] | p [-width-1];
|
||||
if((b22 | (w22 ^ 1))&1) {
|
||||
demerit += N2;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
return demerit;
|
||||
}
|
||||
|
||||
STATIC_IN_RELEASE int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength)
|
||||
{
|
||||
int head;
|
||||
int i;
|
||||
unsigned char prev;
|
||||
|
||||
if(frame[0] & 1) {
|
||||
runLength[0] = -1;
|
||||
head = 1;
|
||||
} else {
|
||||
head = 0;
|
||||
}
|
||||
runLength[head] = 1;
|
||||
prev = frame[0];
|
||||
|
||||
for(i = 1; i < width; i++) {
|
||||
if((frame[i] ^ prev) & 1) {
|
||||
head++;
|
||||
runLength[head] = 1;
|
||||
prev = frame[i];
|
||||
} else {
|
||||
runLength[head]++;
|
||||
}
|
||||
}
|
||||
|
||||
return head + 1;
|
||||
}
|
||||
|
||||
STATIC_IN_RELEASE int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength)
|
||||
{
|
||||
int head;
|
||||
int i;
|
||||
unsigned char prev;
|
||||
|
||||
if(frame[0] & 1) {
|
||||
runLength[0] = -1;
|
||||
head = 1;
|
||||
} else {
|
||||
head = 0;
|
||||
}
|
||||
runLength[head] = 1;
|
||||
prev = frame[0];
|
||||
|
||||
for(i = 1; i < width; i++) {
|
||||
if((frame[i * width] ^ prev) & 1) {
|
||||
head++;
|
||||
runLength[head] = 1;
|
||||
prev = frame[i * width];
|
||||
} else {
|
||||
runLength[head]++;
|
||||
}
|
||||
}
|
||||
|
||||
return head + 1;
|
||||
}
|
||||
|
||||
STATIC_IN_RELEASE int Mask_evaluateSymbol(int width, unsigned char *frame)
|
||||
{
|
||||
int x, y;
|
||||
int demerit = 0;
|
||||
int runLength[QRSPEC_WIDTH_MAX + 1];
|
||||
int length;
|
||||
|
||||
demerit += Mask_calcN2(width, frame);
|
||||
|
||||
for(y = 0; y < width; y++) {
|
||||
length = Mask_calcRunLengthH(width, frame + y * width, runLength);
|
||||
demerit += Mask_calcN1N3(length, runLength);
|
||||
}
|
||||
|
||||
for(x = 0; x < width; x++) {
|
||||
length = Mask_calcRunLengthV(width, frame + x, runLength);
|
||||
demerit += Mask_calcN1N3(length, runLength);
|
||||
}
|
||||
|
||||
return demerit;
|
||||
}
|
||||
|
||||
unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level)
|
||||
{
|
||||
int i;
|
||||
unsigned char *mask, *bestMask;
|
||||
int minDemerit = INT_MAX;
|
||||
int blacks;
|
||||
int bratio;
|
||||
int demerit;
|
||||
int w2 = width * width;
|
||||
|
||||
mask = (unsigned char *)malloc((size_t)w2);
|
||||
if(mask == NULL) return NULL;
|
||||
bestMask = (unsigned char *)malloc((size_t)w2);
|
||||
if(bestMask == NULL) {
|
||||
free(mask);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(i = 0; i < maskNum; i++) {
|
||||
// n1 = n2 = n3 = n4 = 0;
|
||||
demerit = 0;
|
||||
blacks = maskMakers[i](width, frame, mask);
|
||||
blacks += Mask_writeFormatInformation(width, mask, i, level);
|
||||
bratio = (200 * blacks + w2) / w2 / 2; /* (int)(100*blacks/w2+0.5) */
|
||||
demerit = (abs(bratio - 50) / 5) * N4;
|
||||
// n4 = demerit;
|
||||
demerit += Mask_evaluateSymbol(width, mask);
|
||||
// printf("(%d,%d,%d,%d)=%d\n", n1, n2, n3 ,n4, demerit);
|
||||
if(demerit < minDemerit) {
|
||||
minDemerit = demerit;
|
||||
memcpy(bestMask, mask, (size_t)w2);
|
||||
}
|
||||
}
|
||||
free(mask);
|
||||
return bestMask;
|
||||
}
|
39
src/qrcode/mask.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Masking.
|
||||
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MASK_H
|
||||
#define MASK_H
|
||||
|
||||
#include "qrencode.h"
|
||||
extern unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level);
|
||||
extern unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level);
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
extern int Mask_calcN2(int width, unsigned char *frame);
|
||||
extern int Mask_calcN1N3(int length, int *runLength);
|
||||
extern int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength);
|
||||
extern int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength);
|
||||
extern int Mask_evaluateSymbol(int width, unsigned char *frame);
|
||||
extern int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level);
|
||||
extern unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask);
|
||||
#endif
|
||||
|
||||
#endif /* MASK_H */
|
177
src/qrcode/mmask.cpp
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Masking for Micro QR Code.
|
||||
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "qrencode.h"
|
||||
#include "mqrspec.h"
|
||||
#include "mmask.h"
|
||||
|
||||
STATIC_IN_RELEASE void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level)
|
||||
{
|
||||
unsigned int format;
|
||||
unsigned char v;
|
||||
int i;
|
||||
|
||||
format = MQRspec_getFormatInfo(mask, version, level);
|
||||
|
||||
for(i = 0; i < 8; i++) {
|
||||
v = 0x84 | (format & 1);
|
||||
frame[width * (i + 1) + 8] = v;
|
||||
format = format >> 1;
|
||||
}
|
||||
for(i = 0; i < 7; i++) {
|
||||
v = 0x84 | (format & 1);
|
||||
frame[width * 8 + 7 - i] = v;
|
||||
format = format >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
#define MASKMAKER(__exp__) \
|
||||
int x, y;\
|
||||
\
|
||||
for(y = 0; y < width; y++) {\
|
||||
for(x = 0; x < width; x++) {\
|
||||
if(*s & 0x80) {\
|
||||
*d = *s;\
|
||||
} else {\
|
||||
*d = *s ^ ((__exp__) == 0);\
|
||||
}\
|
||||
s++; d++;\
|
||||
}\
|
||||
}
|
||||
|
||||
static void Mask_mask0(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER(y&1)
|
||||
}
|
||||
|
||||
static void Mask_mask1(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER(((y/2)+(x/3))&1)
|
||||
}
|
||||
|
||||
static void Mask_mask2(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER((((x*y)&1)+(x*y)%3)&1)
|
||||
}
|
||||
|
||||
static void Mask_mask3(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER((((x+y)&1)+((x*y)%3))&1)
|
||||
}
|
||||
|
||||
#define maskNum (4)
|
||||
typedef void MaskMaker(int, const unsigned char *, unsigned char *);
|
||||
static MaskMaker *maskMakers[maskNum] = {
|
||||
Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3
|
||||
};
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask)
|
||||
{
|
||||
unsigned char *masked;
|
||||
|
||||
masked = (unsigned char *)malloc((size_t)(width * width));
|
||||
if(masked == NULL) return NULL;
|
||||
|
||||
maskMakers[mask](width, frame, masked);
|
||||
|
||||
return masked;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level)
|
||||
{
|
||||
unsigned char *masked;
|
||||
int width;
|
||||
|
||||
if(mask < 0 || mask >= maskNum) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
width = MQRspec_getWidth(version);
|
||||
masked = (unsigned char *)malloc((size_t)(width * width));
|
||||
if(masked == NULL) return NULL;
|
||||
|
||||
maskMakers[mask](width, frame, masked);
|
||||
MMask_writeFormatInformation(version, width, masked, mask, level);
|
||||
|
||||
return masked;
|
||||
}
|
||||
|
||||
STATIC_IN_RELEASE int MMask_evaluateSymbol(int width, unsigned char *frame)
|
||||
{
|
||||
int x, y;
|
||||
unsigned char *p;
|
||||
int sum1 = 0, sum2 = 0;
|
||||
|
||||
p = frame + width * (width - 1);
|
||||
for(x = 1; x < width; x++) {
|
||||
sum1 += (p[x] & 1);
|
||||
}
|
||||
|
||||
p = frame + width * 2 - 1;
|
||||
for(y = 1; y < width; y++) {
|
||||
sum2 += (*p & 1);
|
||||
p += width;
|
||||
}
|
||||
|
||||
return (sum1 <= sum2)?(sum1 * 16 + sum2):(sum2 * 16 + sum1);
|
||||
}
|
||||
|
||||
unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level)
|
||||
{
|
||||
int i;
|
||||
unsigned char *mask, *bestMask;
|
||||
int maxScore = 0;
|
||||
int score;
|
||||
int width;
|
||||
|
||||
width = MQRspec_getWidth(version);
|
||||
|
||||
mask = (unsigned char *)malloc((size_t)(width * width));
|
||||
if(mask == NULL) return NULL;
|
||||
bestMask = NULL;
|
||||
|
||||
for(i = 0; i < maskNum; i++) {
|
||||
score = 0;
|
||||
maskMakers[i](width, frame, mask);
|
||||
MMask_writeFormatInformation(version, width, mask, i, level);
|
||||
score = MMask_evaluateSymbol(width, mask);
|
||||
if(score > maxScore) {
|
||||
maxScore = score;
|
||||
free(bestMask);
|
||||
bestMask = mask;
|
||||
mask = (unsigned char *)malloc((size_t)(width * width));
|
||||
if(mask == NULL) break;
|
||||
}
|
||||
}
|
||||
free(mask);
|
||||
return bestMask;
|
||||
}
|
35
src/qrcode/mmask.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Masking for Micro QR Code.
|
||||
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MMASK_H
|
||||
#define MMASK_H
|
||||
|
||||
#include "qrencode.h"
|
||||
extern unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level);
|
||||
extern unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level);
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
extern int MMask_evaluateSymbol(int width, unsigned char *frame);
|
||||
extern void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level);
|
||||
extern unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask);
|
||||
#endif
|
||||
|
||||
#endif /* MMASK_H */
|
232
src/qrcode/mqrspec.cpp
Normal file
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Micro QR Code specification in convenient format.
|
||||
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* The following data / specifications are taken from
|
||||
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
|
||||
* or
|
||||
* "Automatic identification and data capture techniques --
|
||||
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mqrspec.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Version and capacity
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int width; ///< Edge length of the symbol
|
||||
int ec[4]; ///< Number of ECC code (bytes)
|
||||
} MQRspec_Capacity;
|
||||
|
||||
/**
|
||||
* Table of the capacity of symbols
|
||||
* See Table 1 (pp.106) and Table 8 (pp.113) of Appendix 1, JIS X0510:2004.
|
||||
*/
|
||||
static const MQRspec_Capacity mqrspecCapacity[MQRSPEC_VERSION_MAX + 1] = {
|
||||
{ 0, {0, 0, 0, 0}},
|
||||
{ 11, {2, 0, 0, 0}},
|
||||
{ 13, {5, 6, 0, 0}},
|
||||
{ 15, {6, 8, 0, 0}},
|
||||
{ 17, {8, 10, 14, 0}}
|
||||
};
|
||||
|
||||
int MQRspec_getDataLengthBit(int version, QRecLevel level)
|
||||
{
|
||||
int w;
|
||||
int ecc;
|
||||
|
||||
w = mqrspecCapacity[version].width - 1;
|
||||
ecc = mqrspecCapacity[version].ec[level];
|
||||
if(ecc == 0) return 0;
|
||||
return w * w - 64 - ecc * 8;
|
||||
}
|
||||
|
||||
int MQRspec_getDataLength(int version, QRecLevel level)
|
||||
{
|
||||
return (MQRspec_getDataLengthBit(version, level) + 4) / 8;
|
||||
}
|
||||
|
||||
int MQRspec_getECCLength(int version, QRecLevel level)
|
||||
{
|
||||
return mqrspecCapacity[version].ec[level];
|
||||
}
|
||||
|
||||
int MQRspec_getWidth(int version)
|
||||
{
|
||||
return mqrspecCapacity[version].width;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Length indicator
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* See Table 3 (pp.107) of Appendix 1, JIS X0510:2004.
|
||||
*/
|
||||
static const int lengthTableBits[4][4] = {
|
||||
{ 3, 4, 5, 6},
|
||||
{ 0, 3, 4, 5},
|
||||
{ 0, 0, 4, 5},
|
||||
{ 0, 0, 3, 4}
|
||||
};
|
||||
|
||||
int MQRspec_lengthIndicator(QRencodeMode mode, int version)
|
||||
{
|
||||
return lengthTableBits[mode][version - 1];
|
||||
}
|
||||
|
||||
int MQRspec_maximumWords(QRencodeMode mode, int version)
|
||||
{
|
||||
int bits;
|
||||
int words;
|
||||
|
||||
bits = lengthTableBits[mode][version - 1];
|
||||
words = (1 << bits) - 1;
|
||||
if(mode == QR_MODE_KANJI) {
|
||||
words *= 2; // the number of bytes is required
|
||||
}
|
||||
|
||||
return words;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Format information
|
||||
*****************************************************************************/
|
||||
|
||||
/* See calcFormatInfo in tests/test_mqrspec.c */
|
||||
static const unsigned int formatInfo[4][8] = {
|
||||
{0x4445, 0x55ae, 0x6793, 0x7678, 0x06de, 0x1735, 0x2508, 0x34e3},
|
||||
{0x4172, 0x5099, 0x62a4, 0x734f, 0x03e9, 0x1202, 0x203f, 0x31d4},
|
||||
{0x4e2b, 0x5fc0, 0x6dfd, 0x7c16, 0x0cb0, 0x1d5b, 0x2f66, 0x3e8d},
|
||||
{0x4b1c, 0x5af7, 0x68ca, 0x7921, 0x0987, 0x186c, 0x2a51, 0x3bba}
|
||||
};
|
||||
|
||||
/* See Table 10 of Appendix 1. (pp.115) */
|
||||
static const int typeTable[MQRSPEC_VERSION_MAX + 1][3] = {
|
||||
{-1, -1, -1},
|
||||
{ 0, -1, -1},
|
||||
{ 1, 2, -1},
|
||||
{ 3, 4, -1},
|
||||
{ 5, 6, 7}
|
||||
};
|
||||
|
||||
unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level)
|
||||
{
|
||||
int type;
|
||||
|
||||
if(mask < 0 || mask > 3) return 0;
|
||||
if(version <= 0 || version > MQRSPEC_VERSION_MAX) return 0;
|
||||
if(level == QR_ECLEVEL_H) return 0;
|
||||
type = typeTable[version][level];
|
||||
if(type < 0) return 0;
|
||||
|
||||
return formatInfo[mask][type];
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Frame
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Put a finder pattern.
|
||||
* @param frame
|
||||
* @param width
|
||||
* @param ox,oy upper-left coordinate of the pattern
|
||||
*/
|
||||
static void putFinderPattern(unsigned char *frame, int width, int ox, int oy)
|
||||
{
|
||||
static const unsigned char finder[] = {
|
||||
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
|
||||
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
|
||||
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
|
||||
};
|
||||
int x, y;
|
||||
const unsigned char *s;
|
||||
|
||||
frame += oy * width + ox;
|
||||
s = finder;
|
||||
for(y = 0; y < 7; y++) {
|
||||
for(x = 0; x < 7; x++) {
|
||||
frame[x] = s[x];
|
||||
}
|
||||
frame += width;
|
||||
s += 7;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char *MQRspec_createFrame(int version)
|
||||
{
|
||||
unsigned char *frame, *p, *q;
|
||||
int width;
|
||||
int x, y;
|
||||
|
||||
width = mqrspecCapacity[version].width;
|
||||
frame = (unsigned char *)malloc((size_t)(width * width));
|
||||
if(frame == NULL) return NULL;
|
||||
|
||||
memset(frame, 0, (size_t)(width * width));
|
||||
/* Finder pattern */
|
||||
putFinderPattern(frame, width, 0, 0);
|
||||
/* Separator */
|
||||
p = frame;
|
||||
for(y = 0; y < 7; y++) {
|
||||
p[7] = 0xc0;
|
||||
p += width;
|
||||
}
|
||||
memset(frame + width * 7, 0xc0, 8);
|
||||
/* Mask format information area */
|
||||
memset(frame + width * 8 + 1, 0x84, 8);
|
||||
p = frame + width + 8;
|
||||
for(y = 0; y < 7; y++) {
|
||||
*p = 0x84;
|
||||
p += width;
|
||||
}
|
||||
/* Timing pattern */
|
||||
p = frame + 8;
|
||||
q = frame + width * 8;
|
||||
for(x = 1; x < width-7; x++) {
|
||||
*p = 0x90 | (x & 1);
|
||||
*q = 0x90 | (x & 1);
|
||||
p++;
|
||||
q += width;
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
unsigned char *MQRspec_newFrame(int version)
|
||||
{
|
||||
if(version < 1 || version > MQRSPEC_VERSION_MAX) return NULL;
|
||||
|
||||
return MQRspec_createFrame(version);
|
||||
}
|
150
src/qrcode/mqrspec.h
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Micro QR Code specification in convenient format.
|
||||
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef MQRSPEC_H
|
||||
#define MQRSPEC_H
|
||||
|
||||
#include "qrencode.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Version and capacity
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Maximum width of a symbol
|
||||
*/
|
||||
#define MQRSPEC_WIDTH_MAX 17
|
||||
|
||||
/**
|
||||
* Return maximum data code length (bits) for the version.
|
||||
* @param version version of the symbol
|
||||
* @param level error correction level
|
||||
* @return maximum size (bits)
|
||||
*/
|
||||
extern int MQRspec_getDataLengthBit(int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return maximum data code length (bytes) for the version.
|
||||
* @param version version of the symbol
|
||||
* @param level error correction level
|
||||
* @return maximum size (bytes)
|
||||
*/
|
||||
extern int MQRspec_getDataLength(int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return maximum error correction code length (bytes) for the version.
|
||||
* @param version version of the symbol
|
||||
* @param level error correction level
|
||||
* @return ECC size (bytes)
|
||||
*/
|
||||
extern int MQRspec_getECCLength(int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return a version number that satisfies the input code length.
|
||||
* @param size input code length (byte)
|
||||
* @param level error correction level
|
||||
* @return version number
|
||||
*/
|
||||
extern int MQRspec_getMinimumVersion(int size, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return the width of the symbol for the version.
|
||||
* @param version version of the symbol
|
||||
* @return width
|
||||
*/
|
||||
extern int MQRspec_getWidth(int version);
|
||||
|
||||
/**
|
||||
* Return the numer of remainder bits.
|
||||
* @param version version of the symbol
|
||||
* @return number of remainder bits
|
||||
*/
|
||||
extern int MQRspec_getRemainder(int version);
|
||||
|
||||
/******************************************************************************
|
||||
* Length indicator
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return the size of length indicator for the mode and version.
|
||||
* @param mode encode mode
|
||||
* @param version vesion of the symbol
|
||||
* @return the size of the appropriate length indicator (bits).
|
||||
*/
|
||||
extern int MQRspec_lengthIndicator(QRencodeMode mode, int version);
|
||||
|
||||
/**
|
||||
* Return the maximum length for the mode and version.
|
||||
* @param mode encode mode
|
||||
* @param version vesion of the symbol
|
||||
* @return the maximum length (bytes)
|
||||
*/
|
||||
extern int MQRspec_maximumWords(QRencodeMode mode, int version);
|
||||
|
||||
/******************************************************************************
|
||||
* Version information pattern
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return BCH encoded version information pattern that is used for the symbol
|
||||
* of version 7 or greater. Use lower 18 bits.
|
||||
* @param version vesion of the symbol
|
||||
* @return BCH encoded version information pattern
|
||||
*/
|
||||
extern unsigned int MQRspec_getVersionPattern(int version);
|
||||
|
||||
/******************************************************************************
|
||||
* Format information
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return BCH encoded format information pattern.
|
||||
* @param mask mask number
|
||||
* @param version version of the symbol
|
||||
* @param level error correction level
|
||||
* @return BCH encoded format information pattern
|
||||
*/
|
||||
extern unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level);
|
||||
|
||||
/******************************************************************************
|
||||
* Frame
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return a copy of initialized frame.
|
||||
* @param version version of the symbol
|
||||
* @return Array of unsigned char. You can free it by free().
|
||||
*/
|
||||
extern unsigned char *MQRspec_newFrame(int version);
|
||||
|
||||
/******************************************************************************
|
||||
* Mode indicator
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Mode indicator. See Table 2 in Appendix 1 of JIS X0510:2004, pp.107.
|
||||
*/
|
||||
#define MQRSPEC_MODEID_NUM 0
|
||||
#define MQRSPEC_MODEID_AN 1
|
||||
#define MQRSPEC_MODEID_8 2
|
||||
#define MQRSPEC_MODEID_KANJI 3
|
||||
|
||||
#endif /* MQRSPEC_H */
|
938
src/qrcode/qrencode.cpp
Normal file
@ -0,0 +1,938 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "qrencode.h"
|
||||
#include "qrspec.h"
|
||||
#include "mqrspec.h"
|
||||
#include "bitstream.h"
|
||||
#include "qrinput.h"
|
||||
#include "rsecc.h"
|
||||
#include "split.h"
|
||||
#include "mask.h"
|
||||
#include "mmask.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Raw code
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int dataLength;
|
||||
int eccLength;
|
||||
unsigned char *data;
|
||||
unsigned char *ecc;
|
||||
} RSblock;
|
||||
|
||||
typedef struct {
|
||||
int version;
|
||||
int dataLength;
|
||||
int eccLength;
|
||||
unsigned char *datacode;
|
||||
unsigned char *ecccode;
|
||||
int b1;
|
||||
int blocks;
|
||||
RSblock *rsblock;
|
||||
int count;
|
||||
} QRRawCode;
|
||||
|
||||
static void RSblock_initBlock(RSblock *block, int dl, unsigned char *data, int el, unsigned char *ecc)
|
||||
{
|
||||
block->dataLength = dl;
|
||||
block->data = data;
|
||||
block->eccLength = el;
|
||||
block->ecc = ecc;
|
||||
|
||||
RSECC_encode((size_t)dl, (size_t)el, data, ecc);
|
||||
}
|
||||
|
||||
static int RSblock_init(RSblock *blocks, int spec[5], unsigned char *data, unsigned char *ecc)
|
||||
{
|
||||
int i;
|
||||
RSblock *block;
|
||||
unsigned char *dp, *ep;
|
||||
int el, dl;
|
||||
|
||||
dl = QRspec_rsDataCodes1(spec);
|
||||
el = QRspec_rsEccCodes1(spec);
|
||||
|
||||
block = blocks;
|
||||
dp = data;
|
||||
ep = ecc;
|
||||
for(i = 0; i < QRspec_rsBlockNum1(spec); i++) {
|
||||
RSblock_initBlock(block, dl, dp, el, ep);
|
||||
dp += dl;
|
||||
ep += el;
|
||||
block++;
|
||||
}
|
||||
|
||||
if(QRspec_rsBlockNum2(spec) == 0) return 0;
|
||||
|
||||
dl = QRspec_rsDataCodes2(spec);
|
||||
el = QRspec_rsEccCodes2(spec);
|
||||
for(i = 0; i < QRspec_rsBlockNum2(spec); i++) {
|
||||
RSblock_initBlock(block, dl, dp, el, ep);
|
||||
dp += dl;
|
||||
ep += el;
|
||||
block++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC_IN_RELEASE void QRraw_free(QRRawCode *raw);
|
||||
STATIC_IN_RELEASE QRRawCode *QRraw_new(QRinput *input)
|
||||
{
|
||||
QRRawCode *raw;
|
||||
int spec[5], ret;
|
||||
|
||||
raw = (QRRawCode *)malloc(sizeof(QRRawCode));
|
||||
if(raw == NULL) return NULL;
|
||||
|
||||
raw->datacode = QRinput_getByteStream(input);
|
||||
if(raw->datacode == NULL) {
|
||||
free(raw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QRspec_getEccSpec(input->version, input->level, spec);
|
||||
|
||||
raw->version = input->version;
|
||||
raw->b1 = QRspec_rsBlockNum1(spec);
|
||||
raw->dataLength = QRspec_rsDataLength(spec);
|
||||
raw->eccLength = QRspec_rsEccLength(spec);
|
||||
raw->ecccode = (unsigned char *)malloc((size_t)raw->eccLength);
|
||||
if(raw->ecccode == NULL) {
|
||||
free(raw->datacode);
|
||||
free(raw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
raw->blocks = QRspec_rsBlockNum(spec);
|
||||
raw->rsblock = (RSblock *)calloc((size_t)(raw->blocks), sizeof(RSblock));
|
||||
if(raw->rsblock == NULL) {
|
||||
QRraw_free(raw);
|
||||
return NULL;
|
||||
}
|
||||
ret = RSblock_init(raw->rsblock, spec, raw->datacode, raw->ecccode);
|
||||
if(ret < 0) {
|
||||
QRraw_free(raw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
raw->count = 0;
|
||||
|
||||
return raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a code (byte).
|
||||
* This function can be called iteratively.
|
||||
* @param raw raw code.
|
||||
* @return code
|
||||
*/
|
||||
STATIC_IN_RELEASE unsigned char QRraw_getCode(QRRawCode *raw)
|
||||
{
|
||||
int col, row;
|
||||
unsigned char ret;
|
||||
|
||||
if(raw->count < raw->dataLength) {
|
||||
row = raw->count % raw->blocks;
|
||||
col = raw->count / raw->blocks;
|
||||
if(col >= raw->rsblock[0].dataLength) {
|
||||
row += raw->b1;
|
||||
}
|
||||
ret = raw->rsblock[row].data[col];
|
||||
} else if(raw->count < raw->dataLength + raw->eccLength) {
|
||||
row = (raw->count - raw->dataLength) % raw->blocks;
|
||||
col = (raw->count - raw->dataLength) / raw->blocks;
|
||||
ret = raw->rsblock[row].ecc[col];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
raw->count++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC_IN_RELEASE void QRraw_free(QRRawCode *raw)
|
||||
{
|
||||
if(raw != NULL) {
|
||||
free(raw->datacode);
|
||||
free(raw->ecccode);
|
||||
free(raw->rsblock);
|
||||
free(raw);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Raw code for Micro QR Code
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int version;
|
||||
int dataLength;
|
||||
int eccLength;
|
||||
unsigned char *datacode;
|
||||
unsigned char *ecccode;
|
||||
RSblock *rsblock;
|
||||
int oddbits;
|
||||
int count;
|
||||
} MQRRawCode;
|
||||
|
||||
STATIC_IN_RELEASE void MQRraw_free(MQRRawCode *raw);
|
||||
STATIC_IN_RELEASE MQRRawCode *MQRraw_new(QRinput *input)
|
||||
{
|
||||
MQRRawCode *raw;
|
||||
|
||||
raw = (MQRRawCode *)malloc(sizeof(MQRRawCode));
|
||||
if(raw == NULL) return NULL;
|
||||
|
||||
raw->version = input->version;
|
||||
raw->dataLength = MQRspec_getDataLength(input->version, input->level);
|
||||
raw->eccLength = MQRspec_getECCLength(input->version, input->level);
|
||||
raw->oddbits = raw->dataLength * 8 - MQRspec_getDataLengthBit(input->version, input->level);
|
||||
raw->datacode = QRinput_getByteStream(input);
|
||||
if(raw->datacode == NULL) {
|
||||
free(raw);
|
||||
return NULL;
|
||||
}
|
||||
raw->ecccode = (unsigned char *)malloc((size_t)raw->eccLength);
|
||||
if(raw->ecccode == NULL) {
|
||||
free(raw->datacode);
|
||||
free(raw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
raw->rsblock = (RSblock *)calloc(1, sizeof(RSblock));
|
||||
if(raw->rsblock == NULL) {
|
||||
MQRraw_free(raw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RSblock_initBlock(raw->rsblock, raw->dataLength, raw->datacode, raw->eccLength, raw->ecccode);
|
||||
|
||||
raw->count = 0;
|
||||
|
||||
return raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a code (byte).
|
||||
* This function can be called iteratively.
|
||||
* @param raw raw code.
|
||||
* @return code
|
||||
*/
|
||||
STATIC_IN_RELEASE unsigned char MQRraw_getCode(MQRRawCode *raw)
|
||||
{
|
||||
unsigned char ret;
|
||||
|
||||
if(raw->count < raw->dataLength) {
|
||||
ret = raw->datacode[raw->count];
|
||||
} else if(raw->count < raw->dataLength + raw->eccLength) {
|
||||
ret = raw->ecccode[raw->count - raw->dataLength];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
raw->count++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC_IN_RELEASE void MQRraw_free(MQRRawCode *raw)
|
||||
{
|
||||
if(raw != NULL) {
|
||||
free(raw->datacode);
|
||||
free(raw->ecccode);
|
||||
free(raw->rsblock);
|
||||
free(raw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Frame filling
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
unsigned char *frame;
|
||||
int x, y;
|
||||
int dir;
|
||||
int bit;
|
||||
int mqr;
|
||||
} FrameFiller;
|
||||
|
||||
static void FrameFiller_set(FrameFiller *filler, int width, unsigned char *frame, int mqr)
|
||||
{
|
||||
filler->width = width;
|
||||
filler->frame = frame;
|
||||
filler->x = width - 1;
|
||||
filler->y = width - 1;
|
||||
filler->dir = -1;
|
||||
filler->bit = -1;
|
||||
filler->mqr = mqr;
|
||||
}
|
||||
|
||||
static unsigned char *FrameFiller_next(FrameFiller *filler)
|
||||
{
|
||||
unsigned char *p;
|
||||
int x, y, w;
|
||||
|
||||
if(filler->bit == -1) {
|
||||
filler->bit = 0;
|
||||
return filler->frame + filler->y * filler->width + filler->x;
|
||||
}
|
||||
|
||||
x = filler->x;
|
||||
y = filler->y;
|
||||
p = filler->frame;
|
||||
w = filler->width;
|
||||
|
||||
if(filler->bit == 0) {
|
||||
x--;
|
||||
filler->bit++;
|
||||
} else {
|
||||
x++;
|
||||
y += filler->dir;
|
||||
filler->bit--;
|
||||
}
|
||||
|
||||
if(filler->dir < 0) {
|
||||
if(y < 0) {
|
||||
y = 0;
|
||||
x -= 2;
|
||||
filler->dir = 1;
|
||||
if(!filler->mqr && x == 6) {
|
||||
x--;
|
||||
y = 9;
|
||||
}
|
||||
}
|
||||
} else if(y == w) {
|
||||
y = w - 1;
|
||||
x -= 2;
|
||||
filler->dir = -1;
|
||||
if(!filler->mqr && x == 6) {
|
||||
x--;
|
||||
y -= 8;
|
||||
}
|
||||
}
|
||||
if(x < 0 || y < 0) return NULL;
|
||||
|
||||
filler->x = x;
|
||||
filler->y = y;
|
||||
|
||||
if(p[y * w + x] & 0x80) {
|
||||
// This tail recursion could be optimized.
|
||||
return FrameFiller_next(filler);
|
||||
}
|
||||
return &p[y * w + x];
|
||||
}
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
unsigned char *FrameFiller_test(int version)
|
||||
{
|
||||
int width;
|
||||
unsigned char *frame, *p;
|
||||
int i, length;
|
||||
FrameFiller filler;
|
||||
|
||||
width = QRspec_getWidth(version);
|
||||
frame = QRspec_newFrame(version);
|
||||
if(frame == NULL) return NULL;
|
||||
FrameFiller_set(&filler, width, frame, 0);
|
||||
length = QRspec_getDataLength(version, QR_ECLEVEL_L) * 8
|
||||
+ QRspec_getECCLength(version, QR_ECLEVEL_L) * 8
|
||||
+ QRspec_getRemainder(version);
|
||||
for(i = 0; i < length; i++) {
|
||||
p = FrameFiller_next(&filler);
|
||||
if(p == NULL) {
|
||||
free(frame);
|
||||
return NULL;
|
||||
}
|
||||
*p = (unsigned char)(i & 0x7f) | 0x80;
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
unsigned char *FrameFiller_testMQR(int version)
|
||||
{
|
||||
int width;
|
||||
unsigned char *frame, *p;
|
||||
int i, length;
|
||||
FrameFiller filler;
|
||||
|
||||
width = MQRspec_getWidth(version);
|
||||
frame = MQRspec_newFrame(version);
|
||||
if(frame == NULL) return NULL;
|
||||
FrameFiller_set(&filler, width, frame, 1);
|
||||
length = MQRspec_getDataLengthBit(version, QR_ECLEVEL_L)
|
||||
+ MQRspec_getECCLength(version, QR_ECLEVEL_L) * 8;
|
||||
for(i = 0; i < length; i++) {
|
||||
p = FrameFiller_next(&filler);
|
||||
if(p == NULL) {
|
||||
fprintf(stderr, "Frame filler run over the frame!\n");
|
||||
return frame;
|
||||
}
|
||||
*p = (unsigned char)(i & 0x7f) | 0x80;
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* QR-code encoding
|
||||
*****************************************************************************/
|
||||
|
||||
STATIC_IN_RELEASE QRcode *QRcode_new(int version, int width, unsigned char *data)
|
||||
{
|
||||
QRcode *qrcode;
|
||||
|
||||
qrcode = (QRcode *)malloc(sizeof(QRcode));
|
||||
if(qrcode == NULL) return NULL;
|
||||
|
||||
qrcode->version = version;
|
||||
qrcode->width = width;
|
||||
qrcode->data = data;
|
||||
|
||||
return qrcode;
|
||||
}
|
||||
|
||||
void QRcode_free(QRcode *qrcode)
|
||||
{
|
||||
if(qrcode != NULL) {
|
||||
free(qrcode->data);
|
||||
free(qrcode);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC_IN_RELEASE QRcode *QRcode_encodeMask(QRinput *input, int mask)
|
||||
{
|
||||
int width, version;
|
||||
QRRawCode *raw;
|
||||
unsigned char *frame, *masked, *p, code, bit;
|
||||
int i, j;
|
||||
QRcode *qrcode = NULL;
|
||||
FrameFiller filler;
|
||||
|
||||
if(input->mqr) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(input->version < 0 || input->version > QRSPEC_VERSION_MAX) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(!(input->level >= QR_ECLEVEL_L && input->level <= QR_ECLEVEL_H)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
raw = QRraw_new(input);
|
||||
if(raw == NULL) return NULL;
|
||||
|
||||
version = raw->version;
|
||||
width = QRspec_getWidth(version);
|
||||
frame = QRspec_newFrame(version);
|
||||
if(frame == NULL) {
|
||||
QRraw_free(raw);
|
||||
return NULL;
|
||||
}
|
||||
FrameFiller_set(&filler, width, frame, 0);
|
||||
|
||||
/* interleaved data and ecc codes */
|
||||
for(i = 0; i < raw->dataLength; i++) {
|
||||
code = QRraw_getCode(raw);
|
||||
bit = 0x80;
|
||||
for(j = 0; j < 8; j++) {
|
||||
p = FrameFiller_next(&filler);
|
||||
if(p == NULL) goto EXIT;
|
||||
*p = ((bit & code) != 0);
|
||||
bit = bit >> 1;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < raw->eccLength; i++) {
|
||||
code = QRraw_getCode(raw);
|
||||
bit = 0x80;
|
||||
for(j = 0; j < 8; j++) {
|
||||
p = FrameFiller_next(&filler);
|
||||
if(p == NULL) goto EXIT;
|
||||
*p = 0x02 | ((bit & code) != 0);
|
||||
bit = bit >> 1;
|
||||
}
|
||||
}
|
||||
QRraw_free(raw);
|
||||
raw = NULL;
|
||||
/* remainder bits */
|
||||
j = QRspec_getRemainder(version);
|
||||
for(i = 0; i < j; i++) {
|
||||
p = FrameFiller_next(&filler);
|
||||
if(p == NULL) goto EXIT;
|
||||
*p = 0x02;
|
||||
}
|
||||
|
||||
/* masking */
|
||||
if(mask == -2) { // just for debug purpose
|
||||
masked = (unsigned char *)malloc((size_t)(width * width));
|
||||
memcpy(masked, frame, (size_t)(width * width));
|
||||
} else if(mask < 0) {
|
||||
masked = Mask_mask(width, frame, input->level);
|
||||
} else {
|
||||
masked = Mask_makeMask(width, frame, mask, input->level);
|
||||
}
|
||||
if(masked == NULL) {
|
||||
goto EXIT;
|
||||
}
|
||||
qrcode = QRcode_new(version, width, masked);
|
||||
if(qrcode == NULL) {
|
||||
free(masked);
|
||||
}
|
||||
|
||||
EXIT:
|
||||
QRraw_free(raw);
|
||||
free(frame);
|
||||
return qrcode;
|
||||
}
|
||||
|
||||
STATIC_IN_RELEASE QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask)
|
||||
{
|
||||
int width, version;
|
||||
MQRRawCode *raw;
|
||||
unsigned char *frame, *masked, *p, code, bit;
|
||||
int i, j, length;
|
||||
QRcode *qrcode = NULL;
|
||||
FrameFiller filler;
|
||||
|
||||
if(!input->mqr) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(input->version <= 0 || input->version > MQRSPEC_VERSION_MAX) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(!(input->level >= QR_ECLEVEL_L && input->level <= QR_ECLEVEL_Q)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
raw = MQRraw_new(input);
|
||||
if(raw == NULL) return NULL;
|
||||
|
||||
version = raw->version;
|
||||
width = MQRspec_getWidth(version);
|
||||
frame = MQRspec_newFrame(version);
|
||||
if(frame == NULL) {
|
||||
MQRraw_free(raw);
|
||||
return NULL;
|
||||
}
|
||||
FrameFiller_set(&filler, width, frame, 1);
|
||||
|
||||
/* interleaved data and ecc codes */
|
||||
for(i = 0; i < raw->dataLength; i++) {
|
||||
code = MQRraw_getCode(raw);
|
||||
bit = 0x80;
|
||||
if(raw->oddbits && i == raw->dataLength - 1) {
|
||||
length = raw->oddbits;
|
||||
} else {
|
||||
length = 8;
|
||||
}
|
||||
for(j = 0; j < length; j++) {
|
||||
p = FrameFiller_next(&filler);
|
||||
if(p == NULL) goto EXIT;
|
||||
*p = ((bit & code) != 0);
|
||||
bit = bit >> 1;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < raw->eccLength; i++) {
|
||||
code = MQRraw_getCode(raw);
|
||||
bit = 0x80;
|
||||
length = 8;
|
||||
for(j = 0; j < length; j++) {
|
||||
p = FrameFiller_next(&filler);
|
||||
if(p == NULL) goto EXIT;
|
||||
*p = 0x02 | ((bit & code) != 0);
|
||||
bit = bit >> 1;
|
||||
}
|
||||
}
|
||||
MQRraw_free(raw);
|
||||
raw = NULL;
|
||||
|
||||
/* masking */
|
||||
if(mask == -2) { // just for debug purpose
|
||||
masked = (unsigned char *)malloc((size_t)(width * width));
|
||||
memcpy(masked, frame, (size_t)(width * width));
|
||||
} else if(mask < 0) {
|
||||
masked = MMask_mask(version, frame, input->level);
|
||||
} else {
|
||||
masked = MMask_makeMask(version, frame, mask, input->level);
|
||||
}
|
||||
if(masked == NULL) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
qrcode = QRcode_new(version, width, masked);
|
||||
if(qrcode == NULL) {
|
||||
free(masked);
|
||||
}
|
||||
|
||||
EXIT:
|
||||
MQRraw_free(raw);
|
||||
free(frame);
|
||||
return qrcode;
|
||||
}
|
||||
|
||||
QRcode *QRcode_encodeInput(QRinput *input)
|
||||
{
|
||||
if(input->mqr) {
|
||||
return QRcode_encodeMaskMQR(input, -1);
|
||||
} else {
|
||||
return QRcode_encodeMask(input, -1);
|
||||
}
|
||||
}
|
||||
|
||||
static QRcode *QRcode_encodeStringReal(const char *string, int version, QRecLevel level, int mqr, QRencodeMode hint, int casesensitive)
|
||||
{
|
||||
QRinput *input;
|
||||
QRcode *code;
|
||||
int ret;
|
||||
|
||||
if(string == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(hint != QR_MODE_8 && hint != QR_MODE_KANJI) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(mqr) {
|
||||
input = QRinput_newMQR(version, level);
|
||||
} else {
|
||||
input = QRinput_new2(version, level);
|
||||
}
|
||||
if(input == NULL) return NULL;
|
||||
|
||||
ret = Split_splitStringToQRinput(string, input, hint, casesensitive);
|
||||
if(ret < 0) {
|
||||
QRinput_free(input);
|
||||
return NULL;
|
||||
}
|
||||
code = QRcode_encodeInput(input);
|
||||
QRinput_free(input);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
|
||||
{
|
||||
return QRcode_encodeStringReal(string, version, level, 0, hint, casesensitive);
|
||||
}
|
||||
|
||||
QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(version == 0) {
|
||||
version = 1;
|
||||
}
|
||||
for(i = version; i <= MQRSPEC_VERSION_MAX ; i++) {
|
||||
QRcode *code = QRcode_encodeStringReal(string, i, level, 1, hint, casesensitive);
|
||||
if(code != NULL) return code;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static QRcode *QRcode_encodeDataReal(const unsigned char *data, int length, int version, QRecLevel level, int mqr)
|
||||
{
|
||||
QRinput *input;
|
||||
QRcode *code;
|
||||
int ret;
|
||||
|
||||
if(data == NULL || length == 0) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(mqr) {
|
||||
input = QRinput_newMQR(version, level);
|
||||
} else {
|
||||
input = QRinput_new2(version, level);
|
||||
}
|
||||
if(input == NULL) return NULL;
|
||||
|
||||
ret = QRinput_append(input, QR_MODE_8, length, data);
|
||||
if(ret < 0) {
|
||||
QRinput_free(input);
|
||||
return NULL;
|
||||
}
|
||||
code = QRcode_encodeInput(input);
|
||||
QRinput_free(input);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level)
|
||||
{
|
||||
return QRcode_encodeDataReal(data, size, version, level, 0);
|
||||
}
|
||||
|
||||
QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level)
|
||||
{
|
||||
if(string == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
return QRcode_encodeDataReal((unsigned char *)string, (int)strlen(string), version, level, 0);
|
||||
}
|
||||
|
||||
QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(version == 0) {
|
||||
version = 1;
|
||||
}
|
||||
for(i = version; i <= MQRSPEC_VERSION_MAX; i++) {
|
||||
QRcode *code = QRcode_encodeDataReal(data, size, i, level, 1);
|
||||
if(code != NULL) return code;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(string == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(version == 0) {
|
||||
version = 1;
|
||||
}
|
||||
for(i = version; i <= MQRSPEC_VERSION_MAX; i++) {
|
||||
QRcode *code = QRcode_encodeDataReal((unsigned char *)string, (int)strlen(string), i, level, 1);
|
||||
if(code != NULL) return code;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Structured QR-code encoding
|
||||
*****************************************************************************/
|
||||
|
||||
static QRcode_List *QRcode_List_newEntry(void)
|
||||
{
|
||||
QRcode_List *entry;
|
||||
|
||||
entry = (QRcode_List *)malloc(sizeof(QRcode_List));
|
||||
if(entry == NULL) return NULL;
|
||||
|
||||
entry->next = NULL;
|
||||
entry->code = NULL;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static void QRcode_List_freeEntry(QRcode_List *entry)
|
||||
{
|
||||
if(entry != NULL) {
|
||||
QRcode_free(entry->code);
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void QRcode_List_free(QRcode_List *qrlist)
|
||||
{
|
||||
QRcode_List *list = qrlist, *next;
|
||||
|
||||
while(list != NULL) {
|
||||
next = list->next;
|
||||
QRcode_List_freeEntry(list);
|
||||
list = next;
|
||||
}
|
||||
}
|
||||
|
||||
int QRcode_List_size(QRcode_List *qrlist)
|
||||
{
|
||||
QRcode_List *list = qrlist;
|
||||
int size = 0;
|
||||
|
||||
while(list != NULL) {
|
||||
size++;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static unsigned char QRcode_parity(const char *str, int size)
|
||||
{
|
||||
unsigned char parity = 0;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < size; i++) {
|
||||
parity ^= str[i];
|
||||
}
|
||||
|
||||
return parity;
|
||||
}
|
||||
#endif
|
||||
|
||||
QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s)
|
||||
{
|
||||
QRcode_List *head = NULL;
|
||||
QRcode_List *tail = NULL;
|
||||
QRcode_List *entry;
|
||||
QRinput_InputList *list = s->head;
|
||||
|
||||
while(list != NULL) {
|
||||
if(head == NULL) {
|
||||
entry = QRcode_List_newEntry();
|
||||
if(entry == NULL) goto ABORT;
|
||||
head = entry;
|
||||
tail = head;
|
||||
} else {
|
||||
entry = QRcode_List_newEntry();
|
||||
if(entry == NULL) goto ABORT;
|
||||
tail->next = entry;
|
||||
tail = tail->next;
|
||||
}
|
||||
tail->code = QRcode_encodeInput(list->input);
|
||||
if(tail->code == NULL) {
|
||||
goto ABORT;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return head;
|
||||
ABORT:
|
||||
QRcode_List_free(head);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static QRcode_List *QRcode_encodeInputToStructured(QRinput *input)
|
||||
{
|
||||
QRinput_Struct *s;
|
||||
QRcode_List *codes;
|
||||
|
||||
s = QRinput_splitQRinputToStruct(input);
|
||||
if(s == NULL) return NULL;
|
||||
|
||||
codes = QRcode_encodeInputStructured(s);
|
||||
QRinput_Struct_free(s);
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
static QRcode_List *QRcode_encodeDataStructuredReal(
|
||||
int size, const unsigned char *data,
|
||||
int version, QRecLevel level,
|
||||
int eightbit, QRencodeMode hint, int casesensitive)
|
||||
{
|
||||
QRinput *input;
|
||||
QRcode_List *codes;
|
||||
int ret;
|
||||
|
||||
if(version <= 0) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(!eightbit && (hint != QR_MODE_8 && hint != QR_MODE_KANJI)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
input = QRinput_new2(version, level);
|
||||
if(input == NULL) return NULL;
|
||||
|
||||
if(eightbit) {
|
||||
ret = QRinput_append(input, QR_MODE_8, size, data);
|
||||
} else {
|
||||
ret = Split_splitStringToQRinput((char *)data, input, hint, casesensitive);
|
||||
}
|
||||
if(ret < 0) {
|
||||
QRinput_free(input);
|
||||
return NULL;
|
||||
}
|
||||
codes = QRcode_encodeInputToStructured(input);
|
||||
QRinput_free(input);
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level) {
|
||||
return QRcode_encodeDataStructuredReal(size, data, version, level, 1, QR_MODE_NUL, 0);
|
||||
}
|
||||
|
||||
QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level) {
|
||||
if(string == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
return QRcode_encodeDataStructured((int)strlen(string), (unsigned char *)string, version, level);
|
||||
}
|
||||
|
||||
QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
|
||||
{
|
||||
if(string == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
return QRcode_encodeDataStructuredReal((int)strlen(string), (unsigned char *)string, version, level, 0, hint, casesensitive);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* System utilities
|
||||
*****************************************************************************/
|
||||
|
||||
void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version)
|
||||
{
|
||||
if(major_version != NULL) {
|
||||
*major_version = MAJOR_VERSION;
|
||||
}
|
||||
if(minor_version != NULL) {
|
||||
*minor_version = MINOR_VERSION;
|
||||
}
|
||||
if(micro_version != NULL) {
|
||||
*micro_version = MICRO_VERSION;
|
||||
}
|
||||
}
|
||||
|
||||
char *QRcode_APIVersionString(void)
|
||||
{
|
||||
return (char *)VERSION;
|
||||
}
|
||||
|
||||
void QRcode_clearCache(void)
|
||||
{
|
||||
return;
|
||||
}
|
568
src/qrcode/qrencode.h
Normal file
@ -0,0 +1,568 @@
|
||||
/**
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/** \mainpage
|
||||
* Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D
|
||||
* symbology.
|
||||
*
|
||||
* \section encoding Encoding
|
||||
*
|
||||
* There are two methods to encode data: <b>encoding a string/data</b> or
|
||||
* <b>encoding a structured data</b>.
|
||||
*
|
||||
* \subsection encoding-string Encoding a string/data
|
||||
* You can encode a string by calling QRcode_encodeString().
|
||||
* The given string is parsed automatically and encoded. If you want to encode
|
||||
* data that can be represented as a C string style (NUL terminated), you can
|
||||
* simply use this way.
|
||||
*
|
||||
* If the input data contains Kanji (Shift-JIS) characters and you want to
|
||||
* encode them as Kanji in QR Code, you should give QR_MODE_KANJI as a hint.
|
||||
* Otherwise, all of non-alphanumeric characters are encoded as 8-bit data.
|
||||
* If you want to encode a whole string in 8-bit mode, you can use
|
||||
* QRcode_encodeString8bit() instead.
|
||||
*
|
||||
* Please note that a C string can not contain NUL characters. If your data
|
||||
* contains NUL, you must use QRcode_encodeData().
|
||||
*
|
||||
* \subsection encoding-input Encoding a structured data
|
||||
* You can construct a structured input data manually. If the structure of the
|
||||
* input data is known, you can use this method.
|
||||
* At first, create a ::QRinput object by QRinput_new(). Then add input data
|
||||
* to the QRinput object by QRinput_append(). Finally call QRcode_encodeInput()
|
||||
* to encode the QRinput data.
|
||||
* You can reuse the QRinput object again to encode it in other symbols with
|
||||
* different parameters.
|
||||
*
|
||||
* \section result Result
|
||||
* The encoded symbol is generated as a ::QRcode object. It will contain its
|
||||
* version number, the width of the symbol, and an array represents the symbol.
|
||||
* See ::QRcode for the details. You can free the object by QRcode_free().
|
||||
*
|
||||
* Please note that the version of the result may be larger than specified.
|
||||
* In such cases, the input data would be too large to be encoded in a
|
||||
* symbol of the specified version.
|
||||
*
|
||||
* \section structured Structured append
|
||||
* Libqrencode can generate "Structured-appended" symbols that enables to split
|
||||
* a large data set into mulitple QR codes. A QR code reader concatenates
|
||||
* multiple QR code symbols into a string.
|
||||
* Just like QRcode_encodeString(), you can use QRcode_encodeStringStructured()
|
||||
* to generate structured-appended symbols. This functions returns an instance
|
||||
* of ::QRcode_List. The returned list is a singly-linked list of QRcode: you
|
||||
* can retrieve each QR code in this way:
|
||||
*
|
||||
* \code
|
||||
* QRcode_List *qrcodes;
|
||||
* QRcode_List *entry;
|
||||
* QRcode *qrcode;
|
||||
*
|
||||
* qrcodes = QRcode_encodeStringStructured(...);
|
||||
* entry = qrcodes;
|
||||
* while(entry != NULL) {
|
||||
* qrcode = entry->code;
|
||||
* // do something
|
||||
* entry = entry->next;
|
||||
* }
|
||||
* QRcode_List_free(entry);
|
||||
* \endcode
|
||||
*
|
||||
* Instead of using auto-parsing functions, you can construct your own
|
||||
* structured input. At first, instantiate an object of ::QRinput_Struct
|
||||
* by calling QRinput_Struct_new(). This object can hold multiple ::QRinput,
|
||||
* and one QR code is generated for a ::QRinput.
|
||||
* QRinput_Struct_appendInput() appends a ::QRinput to a ::QRinput_Struct
|
||||
* object. In order to generate structured-appended symbols, it is required to
|
||||
* embed headers to each symbol. You can use
|
||||
* QRinput_Struct_insertStructuredAppendHeaders() to insert appropriate
|
||||
* headers to each symbol. You should call this function just once before
|
||||
* encoding symbols.
|
||||
*/
|
||||
|
||||
#ifndef QRENCODE_H
|
||||
#define QRENCODE_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Encoding mode.
|
||||
*/
|
||||
typedef enum {
|
||||
QR_MODE_NUL = -1, ///< Terminator (NUL character). Internal use only
|
||||
QR_MODE_NUM = 0, ///< Numeric mode
|
||||
QR_MODE_AN, ///< Alphabet-numeric mode
|
||||
QR_MODE_8, ///< 8-bit data mode
|
||||
QR_MODE_KANJI, ///< Kanji (shift-jis) mode
|
||||
QR_MODE_STRUCTURE, ///< Internal use only
|
||||
QR_MODE_ECI, ///< ECI mode
|
||||
QR_MODE_FNC1FIRST, ///< FNC1, first position
|
||||
QR_MODE_FNC1SECOND, ///< FNC1, second position
|
||||
} QRencodeMode;
|
||||
|
||||
/**
|
||||
* Level of error correction.
|
||||
*/
|
||||
typedef enum {
|
||||
QR_ECLEVEL_L = 0, ///< lowest
|
||||
QR_ECLEVEL_M,
|
||||
QR_ECLEVEL_Q,
|
||||
QR_ECLEVEL_H ///< highest
|
||||
} QRecLevel;
|
||||
|
||||
/**
|
||||
* Maximum version (size) of QR-code symbol.
|
||||
*/
|
||||
#define QRSPEC_VERSION_MAX 40
|
||||
|
||||
/**
|
||||
* Maximum version (size) of QR-code symbol.
|
||||
*/
|
||||
#define MQRSPEC_VERSION_MAX 4
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Input data (qrinput.c)
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Singly linked list to contain input strings. An instance of this class
|
||||
* contains its version and error correction level too. It is required to
|
||||
* set them by QRinput_setVersion() and QRinput_setErrorCorrectionLevel(),
|
||||
* or use QRinput_new2() to instantiate an object.
|
||||
*/
|
||||
typedef struct _QRinput QRinput;
|
||||
|
||||
/**
|
||||
* Instantiate an input data object. The version is set to 0 (auto-select)
|
||||
* and the error correction level is set to QR_ECLEVEL_L.
|
||||
* @return an input object (initialized). On error, NULL is returned and errno
|
||||
* is set to indicate the error.
|
||||
* @throw ENOMEM unable to allocate memory.
|
||||
*/
|
||||
extern QRinput *QRinput_new(void);
|
||||
|
||||
/**
|
||||
* Instantiate an input data object.
|
||||
* @param version version number.
|
||||
* @param level Error correction level.
|
||||
* @return an input object (initialized). On error, NULL is returned and errno
|
||||
* is set to indicate the error.
|
||||
* @throw ENOMEM unable to allocate memory for input objects.
|
||||
* @throw EINVAL invalid arguments.
|
||||
*/
|
||||
extern QRinput *QRinput_new2(int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Instantiate an input data object. Object's Micro QR Code flag is set.
|
||||
* Unlike with full-sized QR Code, version number must be specified (>0).
|
||||
* @param version version number (1--4).
|
||||
* @param level Error correction level.
|
||||
* @return an input object (initialized). On error, NULL is returned and errno
|
||||
* is set to indicate the error.
|
||||
* @throw ENOMEM unable to allocate memory for input objects.
|
||||
* @throw EINVAL invalid arguments.
|
||||
*/
|
||||
extern QRinput *QRinput_newMQR(int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Append data to an input object.
|
||||
* The data is copied and appended to the input object.
|
||||
* @param input input object.
|
||||
* @param mode encoding mode.
|
||||
* @param size size of data (byte).
|
||||
* @param data a pointer to the memory area of the input data.
|
||||
* @retval 0 success.
|
||||
* @retval -1 an error occurred and errno is set to indeicate the error.
|
||||
* See Execptions for the details.
|
||||
* @throw ENOMEM unable to allocate memory.
|
||||
* @throw EINVAL input data is invalid.
|
||||
*
|
||||
*/
|
||||
extern int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data);
|
||||
|
||||
/**
|
||||
* Append ECI header.
|
||||
* @param input input object.
|
||||
* @param ecinum ECI indicator number (0 - 999999)
|
||||
* @retval 0 success.
|
||||
* @retval -1 an error occurred and errno is set to indeicate the error.
|
||||
* See Execptions for the details.
|
||||
* @throw ENOMEM unable to allocate memory.
|
||||
* @throw EINVAL input data is invalid.
|
||||
*
|
||||
*/
|
||||
extern int QRinput_appendECIheader(QRinput *input, unsigned int ecinum);
|
||||
|
||||
/**
|
||||
* Get current version.
|
||||
* @param input input object.
|
||||
* @return current version.
|
||||
*/
|
||||
extern int QRinput_getVersion(QRinput *input);
|
||||
|
||||
/**
|
||||
* Set version of the QR code that is to be encoded.
|
||||
* This function cannot be applied to Micro QR Code.
|
||||
* @param input input object.
|
||||
* @param version version number (0 = auto)
|
||||
* @retval 0 success.
|
||||
* @retval -1 invalid argument.
|
||||
*/
|
||||
extern int QRinput_setVersion(QRinput *input, int version);
|
||||
|
||||
/**
|
||||
* Get current error correction level.
|
||||
* @param input input object.
|
||||
* @return Current error correcntion level.
|
||||
*/
|
||||
extern QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input);
|
||||
|
||||
/**
|
||||
* Set error correction level of the QR code that is to be encoded.
|
||||
* This function cannot be applied to Micro QR Code.
|
||||
* @param input input object.
|
||||
* @param level Error correction level.
|
||||
* @retval 0 success.
|
||||
* @retval -1 invalid argument.
|
||||
*/
|
||||
extern int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Set version and error correction level of the QR code at once.
|
||||
* This function is recommened for Micro QR Code.
|
||||
* @param input input object.
|
||||
* @param version version number (0 = auto)
|
||||
* @param level Error correction level.
|
||||
* @retval 0 success.
|
||||
* @retval -1 invalid argument.
|
||||
*/
|
||||
extern int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Free the input object.
|
||||
* All of data chunks in the input object are freed too.
|
||||
* @param input input object.
|
||||
*/
|
||||
extern void QRinput_free(QRinput *input);
|
||||
|
||||
/**
|
||||
* Validate the input data.
|
||||
* @param mode encoding mode.
|
||||
* @param size size of data (byte).
|
||||
* @param data a pointer to the memory area of the input data.
|
||||
* @retval 0 success.
|
||||
* @retval -1 invalid arguments.
|
||||
*/
|
||||
extern int QRinput_check(QRencodeMode mode, int size, const unsigned char *data);
|
||||
|
||||
/**
|
||||
* Set of QRinput for structured symbols.
|
||||
*/
|
||||
typedef struct _QRinput_Struct QRinput_Struct;
|
||||
|
||||
/**
|
||||
* Instantiate a set of input data object.
|
||||
* @return an instance of QRinput_Struct. On error, NULL is returned and errno
|
||||
* is set to indicate the error.
|
||||
* @throw ENOMEM unable to allocate memory.
|
||||
*/
|
||||
extern QRinput_Struct *QRinput_Struct_new(void);
|
||||
|
||||
/**
|
||||
* Set parity of structured symbols.
|
||||
* @param s structured input object.
|
||||
* @param parity parity of s.
|
||||
*/
|
||||
extern void QRinput_Struct_setParity(QRinput_Struct *s, unsigned char parity);
|
||||
|
||||
/**
|
||||
* Append a QRinput object to the set. QRinput created by QRinput_newMQR()
|
||||
* will be rejected.
|
||||
* @warning never append the same QRinput object twice or more.
|
||||
* @param s structured input object.
|
||||
* @param input an input object.
|
||||
* @retval >0 number of input objects in the structure.
|
||||
* @retval -1 an error occurred. See Exceptions for the details.
|
||||
* @throw ENOMEM unable to allocate memory.
|
||||
* @throw EINVAL invalid arguments.
|
||||
*/
|
||||
extern int QRinput_Struct_appendInput(QRinput_Struct *s, QRinput *input);
|
||||
|
||||
/**
|
||||
* Free all of QRinput in the set.
|
||||
* @param s a structured input object.
|
||||
*/
|
||||
extern void QRinput_Struct_free(QRinput_Struct *s);
|
||||
|
||||
/**
|
||||
* Split a QRinput to QRinput_Struct. It calculates a parity, set it, then
|
||||
* insert structured-append headers. QRinput created by QRinput_newMQR() will
|
||||
* be rejected.
|
||||
* @param input input object. Version number and error correction level must be
|
||||
* set.
|
||||
* @return a set of input data. On error, NULL is returned, and errno is set
|
||||
* to indicate the error. See Exceptions for the details.
|
||||
* @throw ERANGE input data is too large.
|
||||
* @throw EINVAL invalid input data.
|
||||
* @throw ENOMEM unable to allocate memory.
|
||||
*/
|
||||
extern QRinput_Struct *QRinput_splitQRinputToStruct(QRinput *input);
|
||||
|
||||
/**
|
||||
* Insert structured-append headers to the input structure. It calculates
|
||||
* a parity and set it if the parity is not set yet.
|
||||
* @param s input structure
|
||||
* @retval 0 success.
|
||||
* @retval -1 an error occurred and errno is set to indeicate the error.
|
||||
* See Execptions for the details.
|
||||
* @throw EINVAL invalid input object.
|
||||
* @throw ENOMEM unable to allocate memory.
|
||||
*/
|
||||
extern int QRinput_Struct_insertStructuredAppendHeaders(QRinput_Struct *s);
|
||||
|
||||
/**
|
||||
* Set FNC1-1st position flag.
|
||||
*/
|
||||
extern int QRinput_setFNC1First(QRinput *input);
|
||||
|
||||
/**
|
||||
* Set FNC1-2nd position flag and application identifier.
|
||||
*/
|
||||
extern int QRinput_setFNC1Second(QRinput *input, unsigned char appid);
|
||||
|
||||
/******************************************************************************
|
||||
* QRcode output (qrencode.c)
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* QRcode class.
|
||||
* Symbol data is represented as an array contains width*width uchars.
|
||||
* Each uchar represents a module (dot). If the less significant bit of
|
||||
* the uchar is 1, the corresponding module is black. The other bits are
|
||||
* meaningless for usual applications, but here its specification is described.
|
||||
*
|
||||
* @verbatim
|
||||
MSB 76543210 LSB
|
||||
|||||||`- 1=black/0=white
|
||||
||||||`-- 1=ecc/0=data code area
|
||||
|||||`--- format information
|
||||
||||`---- version information
|
||||
|||`----- timing pattern
|
||||
||`------ alignment pattern
|
||||
|`------- finder pattern and separator
|
||||
`-------- non-data modules (format, timing, etc.)
|
||||
@endverbatim
|
||||
*/
|
||||
typedef struct {
|
||||
int version; ///< version of the symbol
|
||||
int width; ///< width of the symbol
|
||||
unsigned char *data; ///< symbol data
|
||||
} QRcode;
|
||||
|
||||
/**
|
||||
* Singly-linked list of QRcode. Used to represent a structured symbols.
|
||||
* A list is terminated with NULL.
|
||||
*/
|
||||
typedef struct _QRcode_List {
|
||||
QRcode *code;
|
||||
struct _QRcode_List *next;
|
||||
} QRcode_List;
|
||||
|
||||
/**
|
||||
* Create a symbol from the input data.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
* @param input input data.
|
||||
* @return an instance of QRcode class. The version of the result QRcode may
|
||||
* be larger than the designated version. On error, NULL is returned,
|
||||
* and errno is set to indicate the error. See Exceptions for the
|
||||
* details.
|
||||
* @throw EINVAL invalid input object.
|
||||
* @throw ENOMEM unable to allocate memory for input objects.
|
||||
*/
|
||||
extern QRcode *QRcode_encodeInput(QRinput *input);
|
||||
|
||||
/**
|
||||
* Create a symbol from the string. The library automatically parses the input
|
||||
* string and encodes in a QR Code symbol.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
* @param string input string. It must be NUL terminated.
|
||||
* @param version version of the symbol. If 0, the library chooses the minimum
|
||||
* version for the given input data.
|
||||
* @param level error correction level.
|
||||
* @param hint tell the library how Japanese Kanji characters should be
|
||||
* encoded. If QR_MODE_KANJI is given, the library assumes that the
|
||||
* given string contains Shift-JIS characters and encodes them in
|
||||
* Kanji-mode. If QR_MODE_8 is given, all of non-alphanumerical
|
||||
* characters will be encoded as is. If you want to embed UTF-8
|
||||
* string, choose this. Other mode will cause EINVAL error.
|
||||
* @param casesensitive case-sensitive(1) or not(0).
|
||||
* @return an instance of QRcode class. The version of the result QRcode may
|
||||
* be larger than the designated version. On error, NULL is returned,
|
||||
* and errno is set to indicate the error. See Exceptions for the
|
||||
* details.
|
||||
* @throw EINVAL invalid input object.
|
||||
* @throw ENOMEM unable to allocate memory for input objects.
|
||||
* @throw ERANGE input data is too large.
|
||||
*/
|
||||
extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
|
||||
|
||||
/**
|
||||
* Same to QRcode_encodeString(), but encode whole data in 8-bit mode.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
*/
|
||||
extern QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Micro QR Code version of QRcode_encodeString().
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
*/
|
||||
extern QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
|
||||
|
||||
/**
|
||||
* Micro QR Code version of QRcode_encodeString8bit().
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
*/
|
||||
extern QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Encode byte stream (may include '\0') in 8-bit mode.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
* @param size size of the input data.
|
||||
* @param data input data.
|
||||
* @param version version of the symbol. If 0, the library chooses the minimum
|
||||
* version for the given input data.
|
||||
* @param level error correction level.
|
||||
* @throw EINVAL invalid input object.
|
||||
* @throw ENOMEM unable to allocate memory for input objects.
|
||||
* @throw ERANGE input data is too large.
|
||||
*/
|
||||
extern QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Micro QR Code version of QRcode_encodeData().
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
*/
|
||||
extern QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Free the instance of QRcode class.
|
||||
* @param qrcode an instance of QRcode class.
|
||||
*/
|
||||
extern void QRcode_free(QRcode *qrcode);
|
||||
|
||||
/**
|
||||
* Create structured symbols from the input data.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
* @param s input data, structured.
|
||||
* @return a singly-linked list of QRcode.
|
||||
*/
|
||||
extern QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s);
|
||||
|
||||
/**
|
||||
* Create structured symbols from the string. The library automatically parses
|
||||
* the input string and encodes in a QR Code symbol.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
* @param string input string. It must be NUL terminated.
|
||||
* @param version version of the symbol.
|
||||
* @param level error correction level.
|
||||
* @param hint tell the library how Japanese Kanji characters should be
|
||||
* encoded. If QR_MODE_KANJI is given, the library assumes that the
|
||||
* given string contains Shift-JIS characters and encodes them in
|
||||
* Kanji-mode. If QR_MODE_8 is given, all of non-alphanumerical
|
||||
* characters will be encoded as is. If you want to embed UTF-8
|
||||
* string, choose this. Other mode will cause EINVAL error.
|
||||
* @param casesensitive case-sensitive(1) or not(0).
|
||||
* @return a singly-linked list of QRcode. On error, NULL is returned, and
|
||||
* errno is set to indicate the error. See Exceptions for the details.
|
||||
* @throw EINVAL invalid input object.
|
||||
* @throw ENOMEM unable to allocate memory for input objects.
|
||||
*/
|
||||
extern QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
|
||||
|
||||
/**
|
||||
* Same to QRcode_encodeStringStructured(), but encode whole data in 8-bit mode.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
*/
|
||||
extern QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Create structured symbols from byte stream (may include '\0'). Wholde data
|
||||
* are encoded in 8-bit mode.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
* @param size size of the input data.
|
||||
* @param data input dat.
|
||||
* @param version version of the symbol.
|
||||
* @param level error correction level.
|
||||
* @return a singly-linked list of QRcode. On error, NULL is returned, and
|
||||
* errno is set to indicate the error. See Exceptions for the details.
|
||||
* @throw EINVAL invalid input object.
|
||||
* @throw ENOMEM unable to allocate memory for input objects.
|
||||
*/
|
||||
extern QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return the number of symbols included in a QRcode_List.
|
||||
* @param qrlist a head entry of a QRcode_List.
|
||||
* @return number of symbols in the list.
|
||||
*/
|
||||
extern int QRcode_List_size(QRcode_List *qrlist);
|
||||
|
||||
/**
|
||||
* Free the QRcode_List.
|
||||
* @param qrlist a head entry of a QRcode_List.
|
||||
*/
|
||||
extern void QRcode_List_free(QRcode_List *qrlist);
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* System utilities
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return a string that identifies the library version.
|
||||
* @param major_version major version number
|
||||
* @param minor_version minor version number
|
||||
* @param micro_version micro version number
|
||||
*/
|
||||
extern void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version);
|
||||
|
||||
/**
|
||||
* Return a string that identifies the library version.
|
||||
* @return a string identifies the library version. The string is held by the
|
||||
* library. Do NOT free it.
|
||||
*/
|
||||
extern char *QRcode_APIVersionString(void);
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
#ifndef _MSC_VER
|
||||
extern void QRcode_clearCache(void) __attribute__ ((deprecated));
|
||||
#else
|
||||
extern void QRcode_clearCache(void);
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* QRENCODE_H */
|
89
src/qrcode/qrencode_inner.h
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Header for test use
|
||||
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef QRENCODE_INNER_H
|
||||
#define QRENCODE_INNER_H
|
||||
|
||||
/**
|
||||
* This header file includes definitions for test use.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* Raw code
|
||||
*****************************************************************************/
|
||||
|
||||
#include "qrencode.h"
|
||||
typedef struct {
|
||||
int dataLength;
|
||||
int eccLength;
|
||||
unsigned char *data;
|
||||
unsigned char *ecc;
|
||||
} RSblock;
|
||||
|
||||
typedef struct {
|
||||
int version;
|
||||
int dataLength;
|
||||
int eccLength;
|
||||
unsigned char *datacode;
|
||||
unsigned char *ecccode;
|
||||
int b1;
|
||||
int blocks;
|
||||
RSblock *rsblock;
|
||||
int count;
|
||||
} QRRawCode;
|
||||
|
||||
extern QRRawCode *QRraw_new(QRinput *input);
|
||||
extern unsigned char QRraw_getCode(QRRawCode *raw);
|
||||
extern void QRraw_free(QRRawCode *raw);
|
||||
|
||||
/******************************************************************************
|
||||
* Raw code for Micro QR Code
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int version;
|
||||
int dataLength;
|
||||
int eccLength;
|
||||
unsigned char *datacode;
|
||||
unsigned char *ecccode;
|
||||
RSblock *rsblock;
|
||||
int oddbits;
|
||||
int count;
|
||||
} MQRRawCode;
|
||||
|
||||
extern MQRRawCode *MQRraw_new(QRinput *input);
|
||||
extern unsigned char MQRraw_getCode(MQRRawCode *raw);
|
||||
extern void MQRraw_free(MQRRawCode *raw);
|
||||
|
||||
/******************************************************************************
|
||||
* Frame filling
|
||||
*****************************************************************************/
|
||||
extern unsigned char *FrameFiller_test(int version);
|
||||
extern unsigned char *FrameFiller_testMQR(int version);
|
||||
|
||||
/******************************************************************************
|
||||
* QR-code encoding
|
||||
*****************************************************************************/
|
||||
extern QRcode *QRcode_encodeMask(QRinput *input, int mask);
|
||||
extern QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask);
|
||||
extern QRcode *QRcode_new(int version, int width, unsigned char *data);
|
||||
|
||||
#endif /* QRENCODE_INNER_H */
|
1639
src/qrcode/qrinput.cpp
Normal file
124
src/qrcode/qrinput.h
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Input data chunk class
|
||||
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef QRINPUT_H
|
||||
#define QRINPUT_H
|
||||
|
||||
#include "qrencode.h"
|
||||
#include "bitstream.h"
|
||||
|
||||
int QRinput_isSplittableMode(QRencodeMode mode);
|
||||
|
||||
/******************************************************************************
|
||||
* Entry of input data
|
||||
*****************************************************************************/
|
||||
typedef struct _QRinput_List QRinput_List;
|
||||
|
||||
struct _QRinput_List {
|
||||
QRencodeMode mode;
|
||||
int size; ///< Size of data chunk (byte).
|
||||
unsigned char *data; ///< Data chunk.
|
||||
BitStream *bstream;
|
||||
QRinput_List *next;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Input Data
|
||||
*****************************************************************************/
|
||||
struct _QRinput {
|
||||
int version;
|
||||
QRecLevel level;
|
||||
QRinput_List *head;
|
||||
QRinput_List *tail;
|
||||
int mqr;
|
||||
int fnc1;
|
||||
unsigned char appid;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Structured append input data
|
||||
*****************************************************************************/
|
||||
typedef struct _QRinput_InputList QRinput_InputList;
|
||||
|
||||
struct _QRinput_InputList {
|
||||
QRinput *input;
|
||||
QRinput_InputList *next;
|
||||
};
|
||||
|
||||
struct _QRinput_Struct {
|
||||
int size; ///< number of structured symbols
|
||||
int parity;
|
||||
QRinput_InputList *head;
|
||||
QRinput_InputList *tail;
|
||||
};
|
||||
|
||||
/**
|
||||
* Pack all bit streams padding bits into a byte array.
|
||||
* @param input input data.
|
||||
* @return padded merged byte stream
|
||||
*/
|
||||
extern unsigned char *QRinput_getByteStream(QRinput *input);
|
||||
|
||||
|
||||
extern int QRinput_estimateBitsModeNum(int size);
|
||||
extern int QRinput_estimateBitsModeAn(int size);
|
||||
extern int QRinput_estimateBitsMode8(int size);
|
||||
extern int QRinput_estimateBitsModeKanji(int size);
|
||||
|
||||
extern QRinput *QRinput_dup(QRinput *input);
|
||||
|
||||
extern const signed char QRinput_anTable[128];
|
||||
|
||||
/**
|
||||
* Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19).
|
||||
* @param __c__ character
|
||||
* @return value
|
||||
*/
|
||||
#define QRinput_lookAnTable(__c__) \
|
||||
((__c__ & 0x80)?-1:QRinput_anTable[(int)__c__])
|
||||
|
||||
/**
|
||||
* Length of a standard mode indicator in bits.
|
||||
*/
|
||||
|
||||
#define MODE_INDICATOR_SIZE 4
|
||||
|
||||
/**
|
||||
* Length of a segment of structured-append header.
|
||||
*/
|
||||
#define STRUCTURE_HEADER_SIZE 20
|
||||
|
||||
/**
|
||||
* Maximum number of symbols in a set of structured-appended symbols.
|
||||
*/
|
||||
#define MAX_STRUCTURED_SYMBOLS 16
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
extern int QRinput_mergeBitStream(QRinput *input, BitStream *bstream);
|
||||
extern int QRinput_getBitStream(QRinput *input, BitStream *bstream);
|
||||
extern int QRinput_estimateBitStreamSize(QRinput *input, int version);
|
||||
extern int QRinput_splitEntry(QRinput_List *entry, int bytes);
|
||||
extern int QRinput_estimateVersion(QRinput *input);
|
||||
extern int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits);
|
||||
extern int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, unsigned char parity);
|
||||
#endif
|
||||
|
||||
#endif /* QRINPUT_H */
|
514
src/qrcode/qrspec.cpp
Normal file
@ -0,0 +1,514 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* QR Code specification in convenient format.
|
||||
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* The following data / specifications are taken from
|
||||
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
|
||||
* or
|
||||
* "Automatic identification and data capture techniques --
|
||||
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "qrspec.h"
|
||||
#include "qrinput.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Version and capacity
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int width; //< Edge length of the symbol
|
||||
int words; //< Data capacity (bytes)
|
||||
int remainder; //< Remainder bit (bits)
|
||||
int ec[4]; //< Number of ECC code (bytes)
|
||||
} QRspec_Capacity;
|
||||
|
||||
/**
|
||||
* Table of the capacity of symbols
|
||||
* See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004.
|
||||
*/
|
||||
static const QRspec_Capacity qrspecCapacity[QRSPEC_VERSION_MAX + 1] = {
|
||||
{ 0, 0, 0, { 0, 0, 0, 0}},
|
||||
{ 21, 26, 0, { 7, 10, 13, 17}}, // 1
|
||||
{ 25, 44, 7, { 10, 16, 22, 28}},
|
||||
{ 29, 70, 7, { 15, 26, 36, 44}},
|
||||
{ 33, 100, 7, { 20, 36, 52, 64}},
|
||||
{ 37, 134, 7, { 26, 48, 72, 88}}, // 5
|
||||
{ 41, 172, 7, { 36, 64, 96, 112}},
|
||||
{ 45, 196, 0, { 40, 72, 108, 130}},
|
||||
{ 49, 242, 0, { 48, 88, 132, 156}},
|
||||
{ 53, 292, 0, { 60, 110, 160, 192}},
|
||||
{ 57, 346, 0, { 72, 130, 192, 224}}, //10
|
||||
{ 61, 404, 0, { 80, 150, 224, 264}},
|
||||
{ 65, 466, 0, { 96, 176, 260, 308}},
|
||||
{ 69, 532, 0, { 104, 198, 288, 352}},
|
||||
{ 73, 581, 3, { 120, 216, 320, 384}},
|
||||
{ 77, 655, 3, { 132, 240, 360, 432}}, //15
|
||||
{ 81, 733, 3, { 144, 280, 408, 480}},
|
||||
{ 85, 815, 3, { 168, 308, 448, 532}},
|
||||
{ 89, 901, 3, { 180, 338, 504, 588}},
|
||||
{ 93, 991, 3, { 196, 364, 546, 650}},
|
||||
{ 97, 1085, 3, { 224, 416, 600, 700}}, //20
|
||||
{101, 1156, 4, { 224, 442, 644, 750}},
|
||||
{105, 1258, 4, { 252, 476, 690, 816}},
|
||||
{109, 1364, 4, { 270, 504, 750, 900}},
|
||||
{113, 1474, 4, { 300, 560, 810, 960}},
|
||||
{117, 1588, 4, { 312, 588, 870, 1050}}, //25
|
||||
{121, 1706, 4, { 336, 644, 952, 1110}},
|
||||
{125, 1828, 4, { 360, 700, 1020, 1200}},
|
||||
{129, 1921, 3, { 390, 728, 1050, 1260}},
|
||||
{133, 2051, 3, { 420, 784, 1140, 1350}},
|
||||
{137, 2185, 3, { 450, 812, 1200, 1440}}, //30
|
||||
{141, 2323, 3, { 480, 868, 1290, 1530}},
|
||||
{145, 2465, 3, { 510, 924, 1350, 1620}},
|
||||
{149, 2611, 3, { 540, 980, 1440, 1710}},
|
||||
{153, 2761, 3, { 570, 1036, 1530, 1800}},
|
||||
{157, 2876, 0, { 570, 1064, 1590, 1890}}, //35
|
||||
{161, 3034, 0, { 600, 1120, 1680, 1980}},
|
||||
{165, 3196, 0, { 630, 1204, 1770, 2100}},
|
||||
{169, 3362, 0, { 660, 1260, 1860, 2220}},
|
||||
{173, 3532, 0, { 720, 1316, 1950, 2310}},
|
||||
{177, 3706, 0, { 750, 1372, 2040, 2430}} //40
|
||||
};
|
||||
|
||||
int QRspec_getDataLength(int version, QRecLevel level)
|
||||
{
|
||||
return qrspecCapacity[version].words - qrspecCapacity[version].ec[level];
|
||||
}
|
||||
|
||||
int QRspec_getECCLength(int version, QRecLevel level)
|
||||
{
|
||||
return qrspecCapacity[version].ec[level];
|
||||
}
|
||||
|
||||
int QRspec_getMinimumVersion(int size, QRecLevel level)
|
||||
{
|
||||
int i;
|
||||
int words;
|
||||
|
||||
for(i = 1; i <= QRSPEC_VERSION_MAX; i++) {
|
||||
words = qrspecCapacity[i].words - qrspecCapacity[i].ec[level];
|
||||
if(words >= size) return i;
|
||||
}
|
||||
|
||||
return QRSPEC_VERSION_MAX;
|
||||
}
|
||||
|
||||
int QRspec_getWidth(int version)
|
||||
{
|
||||
return qrspecCapacity[version].width;
|
||||
}
|
||||
|
||||
int QRspec_getRemainder(int version)
|
||||
{
|
||||
return qrspecCapacity[version].remainder;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Length indicator
|
||||
*****************************************************************************/
|
||||
|
||||
static const int lengthTableBits[4][3] = {
|
||||
{10, 12, 14},
|
||||
{ 9, 11, 13},
|
||||
{ 8, 16, 16},
|
||||
{ 8, 10, 12}
|
||||
};
|
||||
|
||||
int QRspec_lengthIndicator(QRencodeMode mode, int version)
|
||||
{
|
||||
int l;
|
||||
|
||||
if(!QRinput_isSplittableMode(mode)) return 0;
|
||||
if(version <= 9) {
|
||||
l = 0;
|
||||
} else if(version <= 26) {
|
||||
l = 1;
|
||||
} else {
|
||||
l = 2;
|
||||
}
|
||||
|
||||
return lengthTableBits[mode][l];
|
||||
}
|
||||
|
||||
int QRspec_maximumWords(QRencodeMode mode, int version)
|
||||
{
|
||||
int l;
|
||||
int bits;
|
||||
int words;
|
||||
|
||||
if(!QRinput_isSplittableMode(mode)) return 0;
|
||||
if(version <= 9) {
|
||||
l = 0;
|
||||
} else if(version <= 26) {
|
||||
l = 1;
|
||||
} else {
|
||||
l = 2;
|
||||
}
|
||||
|
||||
bits = lengthTableBits[mode][l];
|
||||
words = (1 << bits) - 1;
|
||||
if(mode == QR_MODE_KANJI) {
|
||||
words *= 2; // the number of bytes is required
|
||||
}
|
||||
|
||||
return words;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Error correction code
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Table of the error correction code (Reed-Solomon block)
|
||||
* See Table 12-16 (pp.30-36), JIS X0510:2004.
|
||||
*/
|
||||
static const int eccTable[QRSPEC_VERSION_MAX+1][4][2] = {
|
||||
{{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}},
|
||||
{{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}}, // 1
|
||||
{{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}},
|
||||
{{ 1, 0}, { 1, 0}, { 2, 0}, { 2, 0}},
|
||||
{{ 1, 0}, { 2, 0}, { 2, 0}, { 4, 0}},
|
||||
{{ 1, 0}, { 2, 0}, { 2, 2}, { 2, 2}}, // 5
|
||||
{{ 2, 0}, { 4, 0}, { 4, 0}, { 4, 0}},
|
||||
{{ 2, 0}, { 4, 0}, { 2, 4}, { 4, 1}},
|
||||
{{ 2, 0}, { 2, 2}, { 4, 2}, { 4, 2}},
|
||||
{{ 2, 0}, { 3, 2}, { 4, 4}, { 4, 4}},
|
||||
{{ 2, 2}, { 4, 1}, { 6, 2}, { 6, 2}}, //10
|
||||
{{ 4, 0}, { 1, 4}, { 4, 4}, { 3, 8}},
|
||||
{{ 2, 2}, { 6, 2}, { 4, 6}, { 7, 4}},
|
||||
{{ 4, 0}, { 8, 1}, { 8, 4}, {12, 4}},
|
||||
{{ 3, 1}, { 4, 5}, {11, 5}, {11, 5}},
|
||||
{{ 5, 1}, { 5, 5}, { 5, 7}, {11, 7}}, //15
|
||||
{{ 5, 1}, { 7, 3}, {15, 2}, { 3, 13}},
|
||||
{{ 1, 5}, {10, 1}, { 1, 15}, { 2, 17}},
|
||||
{{ 5, 1}, { 9, 4}, {17, 1}, { 2, 19}},
|
||||
{{ 3, 4}, { 3, 11}, {17, 4}, { 9, 16}},
|
||||
{{ 3, 5}, { 3, 13}, {15, 5}, {15, 10}}, //20
|
||||
{{ 4, 4}, {17, 0}, {17, 6}, {19, 6}},
|
||||
{{ 2, 7}, {17, 0}, { 7, 16}, {34, 0}},
|
||||
{{ 4, 5}, { 4, 14}, {11, 14}, {16, 14}},
|
||||
{{ 6, 4}, { 6, 14}, {11, 16}, {30, 2}},
|
||||
{{ 8, 4}, { 8, 13}, { 7, 22}, {22, 13}}, //25
|
||||
{{10, 2}, {19, 4}, {28, 6}, {33, 4}},
|
||||
{{ 8, 4}, {22, 3}, { 8, 26}, {12, 28}},
|
||||
{{ 3, 10}, { 3, 23}, { 4, 31}, {11, 31}},
|
||||
{{ 7, 7}, {21, 7}, { 1, 37}, {19, 26}},
|
||||
{{ 5, 10}, {19, 10}, {15, 25}, {23, 25}}, //30
|
||||
{{13, 3}, { 2, 29}, {42, 1}, {23, 28}},
|
||||
{{17, 0}, {10, 23}, {10, 35}, {19, 35}},
|
||||
{{17, 1}, {14, 21}, {29, 19}, {11, 46}},
|
||||
{{13, 6}, {14, 23}, {44, 7}, {59, 1}},
|
||||
{{12, 7}, {12, 26}, {39, 14}, {22, 41}}, //35
|
||||
{{ 6, 14}, { 6, 34}, {46, 10}, { 2, 64}},
|
||||
{{17, 4}, {29, 14}, {49, 10}, {24, 46}},
|
||||
{{ 4, 18}, {13, 32}, {48, 14}, {42, 32}},
|
||||
{{20, 4}, {40, 7}, {43, 22}, {10, 67}},
|
||||
{{19, 6}, {18, 31}, {34, 34}, {20, 61}},//40
|
||||
};
|
||||
|
||||
void QRspec_getEccSpec(int version, QRecLevel level, int spec[5])
|
||||
{
|
||||
int b1, b2;
|
||||
int data, ecc;
|
||||
|
||||
b1 = eccTable[version][level][0];
|
||||
b2 = eccTable[version][level][1];
|
||||
data = QRspec_getDataLength(version, level);
|
||||
ecc = QRspec_getECCLength(version, level);
|
||||
|
||||
if(b2 == 0) {
|
||||
spec[0] = b1;
|
||||
spec[1] = data / b1;
|
||||
spec[2] = ecc / b1;
|
||||
spec[3] = spec[4] = 0;
|
||||
} else {
|
||||
spec[0] = b1;
|
||||
spec[1] = data / (b1 + b2);
|
||||
spec[2] = ecc / (b1 + b2);
|
||||
spec[3] = b2;
|
||||
spec[4] = spec[1] + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Alignment pattern
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Positions of alignment patterns.
|
||||
* This array includes only the second and the third position of the alignment
|
||||
* patterns. Rest of them can be calculated from the distance between them.
|
||||
*
|
||||
* See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
|
||||
*/
|
||||
static const int alignmentPattern[QRSPEC_VERSION_MAX+1][2] = {
|
||||
{ 0, 0},
|
||||
{ 0, 0}, {18, 0}, {22, 0}, {26, 0}, {30, 0}, // 1- 5
|
||||
{34, 0}, {22, 38}, {24, 42}, {26, 46}, {28, 50}, // 6-10
|
||||
{30, 54}, {32, 58}, {34, 62}, {26, 46}, {26, 48}, //11-15
|
||||
{26, 50}, {30, 54}, {30, 56}, {30, 58}, {34, 62}, //16-20
|
||||
{28, 50}, {26, 50}, {30, 54}, {28, 54}, {32, 58}, //21-25
|
||||
{30, 58}, {34, 62}, {26, 50}, {30, 54}, {26, 52}, //26-30
|
||||
{30, 56}, {34, 60}, {30, 58}, {34, 62}, {30, 54}, //31-35
|
||||
{24, 50}, {28, 54}, {32, 58}, {26, 54}, {30, 58}, //35-40
|
||||
};
|
||||
|
||||
/**
|
||||
* Put an alignment marker.
|
||||
* @param frame
|
||||
* @param width
|
||||
* @param ox,oy center coordinate of the pattern
|
||||
*/
|
||||
static void QRspec_putAlignmentMarker(unsigned char *frame, int width, int ox, int oy)
|
||||
{
|
||||
static const unsigned char finder[] = {
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa0, 0xa0, 0xa0, 0xa1,
|
||||
0xa1, 0xa0, 0xa1, 0xa0, 0xa1,
|
||||
0xa1, 0xa0, 0xa0, 0xa0, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
};
|
||||
int x, y;
|
||||
const unsigned char *s;
|
||||
|
||||
frame += (oy - 2) * width + ox - 2;
|
||||
s = finder;
|
||||
for(y = 0; y < 5; y++) {
|
||||
for(x = 0; x < 5; x++) {
|
||||
frame[x] = s[x];
|
||||
}
|
||||
frame += width;
|
||||
s += 5;
|
||||
}
|
||||
}
|
||||
|
||||
static void QRspec_putAlignmentPattern(int version, unsigned char *frame, int width)
|
||||
{
|
||||
int d, w, x, y, cx, cy;
|
||||
|
||||
if(version < 2) return;
|
||||
|
||||
d = alignmentPattern[version][1] - alignmentPattern[version][0];
|
||||
if(d < 0) {
|
||||
w = 2;
|
||||
} else {
|
||||
w = (width - alignmentPattern[version][0]) / d + 2;
|
||||
}
|
||||
|
||||
if(w * w - 3 == 1) {
|
||||
x = alignmentPattern[version][0];
|
||||
y = alignmentPattern[version][0];
|
||||
QRspec_putAlignmentMarker(frame, width, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
cx = alignmentPattern[version][0];
|
||||
for(x = 1; x < w - 1; x++) {
|
||||
QRspec_putAlignmentMarker(frame, width, 6, cx);
|
||||
QRspec_putAlignmentMarker(frame, width, cx, 6);
|
||||
cx += d;
|
||||
}
|
||||
|
||||
cy = alignmentPattern[version][0];
|
||||
for(y = 0; y < w-1; y++) {
|
||||
cx = alignmentPattern[version][0];
|
||||
for(x = 0; x < w-1; x++) {
|
||||
QRspec_putAlignmentMarker(frame, width, cx, cy);
|
||||
cx += d;
|
||||
}
|
||||
cy += d;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Version information pattern
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Version information pattern (BCH coded).
|
||||
* See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
|
||||
*/
|
||||
static const unsigned int versionPattern[QRSPEC_VERSION_MAX - 6] = {
|
||||
0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
|
||||
0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
|
||||
0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
|
||||
0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
|
||||
0x27541, 0x28c69
|
||||
};
|
||||
|
||||
unsigned int QRspec_getVersionPattern(int version)
|
||||
{
|
||||
if(version < 7 || version > QRSPEC_VERSION_MAX) return 0;
|
||||
|
||||
return versionPattern[version - 7];
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Format information
|
||||
*****************************************************************************/
|
||||
|
||||
/* See calcFormatInfo in tests/test_qrspec.c */
|
||||
static const unsigned int formatInfo[4][8] = {
|
||||
{0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976},
|
||||
{0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0},
|
||||
{0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed},
|
||||
{0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b}
|
||||
};
|
||||
|
||||
unsigned int QRspec_getFormatInfo(int mask, QRecLevel level)
|
||||
{
|
||||
if(mask < 0 || mask > 7) return 0;
|
||||
|
||||
return formatInfo[level][mask];
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Frame
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Put a finder pattern.
|
||||
* @param frame
|
||||
* @param width
|
||||
* @param ox,oy upper-left coordinate of the pattern
|
||||
*/
|
||||
static void putFinderPattern(unsigned char *frame, int width, int ox, int oy)
|
||||
{
|
||||
static const unsigned char finder[] = {
|
||||
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
|
||||
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
|
||||
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
|
||||
};
|
||||
int x, y;
|
||||
const unsigned char *s;
|
||||
|
||||
frame += oy * width + ox;
|
||||
s = finder;
|
||||
for(y = 0; y < 7; y++) {
|
||||
for(x = 0; x < 7; x++) {
|
||||
frame[x] = s[x];
|
||||
}
|
||||
frame += width;
|
||||
s += 7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static unsigned char *QRspec_createFrame(int version)
|
||||
{
|
||||
unsigned char *frame, *p, *q;
|
||||
int width;
|
||||
int x, y;
|
||||
unsigned int verinfo, v;
|
||||
|
||||
width = qrspecCapacity[version].width;
|
||||
frame = (unsigned char *)malloc((size_t)(width * width));
|
||||
if(frame == NULL) return NULL;
|
||||
|
||||
memset(frame, 0, (size_t)(width * width));
|
||||
/* Finder pattern */
|
||||
putFinderPattern(frame, width, 0, 0);
|
||||
putFinderPattern(frame, width, width - 7, 0);
|
||||
putFinderPattern(frame, width, 0, width - 7);
|
||||
/* Separator */
|
||||
p = frame;
|
||||
q = frame + width * (width - 7);
|
||||
for(y = 0; y < 7; y++) {
|
||||
p[7] = 0xc0;
|
||||
p[width - 8] = 0xc0;
|
||||
q[7] = 0xc0;
|
||||
p += width;
|
||||
q += width;
|
||||
}
|
||||
memset(frame + width * 7, 0xc0, 8);
|
||||
memset(frame + width * 8 - 8, 0xc0, 8);
|
||||
memset(frame + width * (width - 8), 0xc0, 8);
|
||||
/* Mask format information area */
|
||||
memset(frame + width * 8, 0x84, 9);
|
||||
memset(frame + width * 9 - 8, 0x84, 8);
|
||||
p = frame + 8;
|
||||
for(y = 0; y < 8; y++) {
|
||||
*p = 0x84;
|
||||
p += width;
|
||||
}
|
||||
p = frame + width * (width - 7) + 8;
|
||||
for(y = 0; y < 7; y++) {
|
||||
*p = 0x84;
|
||||
p += width;
|
||||
}
|
||||
/* Timing pattern */
|
||||
p = frame + width * 6 + 8;
|
||||
q = frame + width * 8 + 6;
|
||||
for(x = 1; x < width-15; x++) {
|
||||
*p = 0x90 | (x & 1);
|
||||
*q = 0x90 | (x & 1);
|
||||
p++;
|
||||
q += width;
|
||||
}
|
||||
/* Alignment pattern */
|
||||
QRspec_putAlignmentPattern(version, frame, width);
|
||||
|
||||
/* Version information */
|
||||
if(version >= 7) {
|
||||
verinfo = QRspec_getVersionPattern(version);
|
||||
|
||||
p = frame + width * (width - 11);
|
||||
v = verinfo;
|
||||
for(x = 0; x < 6; x++) {
|
||||
for(y = 0; y < 3; y++) {
|
||||
p[width * y + x] = 0x88 | (v & 1);
|
||||
v = v >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
p = frame + width - 11;
|
||||
v = verinfo;
|
||||
for(y = 0; y < 6; y++) {
|
||||
for(x = 0; x < 3; x++) {
|
||||
p[x] = 0x88 | (v & 1);
|
||||
v = v >> 1;
|
||||
}
|
||||
p += width;
|
||||
}
|
||||
}
|
||||
/* and a little bit... */
|
||||
frame[width * (width - 8) + 8] = 0x81;
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
unsigned char *QRspec_newFrame(int version)
|
||||
{
|
||||
if(version < 1 || version > QRSPEC_VERSION_MAX) return NULL;
|
||||
|
||||
return QRspec_createFrame(version);
|
||||
}
|
174
src/qrcode/qrspec.h
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* QR Code specification in convenient format.
|
||||
* Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef QRSPEC_H
|
||||
#define QRSPEC_H
|
||||
|
||||
#include "qrencode.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Version and capacity
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Maximum width of a symbol
|
||||
*/
|
||||
#define QRSPEC_WIDTH_MAX 177
|
||||
|
||||
/**
|
||||
* Return maximum data code length (bytes) for the version.
|
||||
* @param version version of the symbol
|
||||
* @param level error correction level
|
||||
* @return maximum size (bytes)
|
||||
*/
|
||||
extern int QRspec_getDataLength(int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return maximum error correction code length (bytes) for the version.
|
||||
* @param version version of the symbol
|
||||
* @param level error correction level
|
||||
* @return ECC size (bytes)
|
||||
*/
|
||||
extern int QRspec_getECCLength(int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return a version number that satisfies the input code length.
|
||||
* @param size input code length (byte)
|
||||
* @param level error correction level
|
||||
* @return version number
|
||||
*/
|
||||
extern int QRspec_getMinimumVersion(int size, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return the width of the symbol for the version.
|
||||
* @param version vesion of the symbol
|
||||
* @return width of the symbol
|
||||
*/
|
||||
extern int QRspec_getWidth(int version);
|
||||
|
||||
/**
|
||||
* Return the numer of remainder bits.
|
||||
* @param version vesion of the symbol
|
||||
* @return number of remainder bits
|
||||
*/
|
||||
extern int QRspec_getRemainder(int version);
|
||||
|
||||
/******************************************************************************
|
||||
* Length indicator
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return the size of length indicator for the mode and version.
|
||||
* @param mode encode mode
|
||||
* @param version vesion of the symbol
|
||||
* @return the size of the appropriate length indicator (bits).
|
||||
*/
|
||||
extern int QRspec_lengthIndicator(QRencodeMode mode, int version);
|
||||
|
||||
/**
|
||||
* Return the maximum length for the mode and version.
|
||||
* @param mode encode mode
|
||||
* @param version vesion of the symbol
|
||||
* @return the maximum length (bytes)
|
||||
*/
|
||||
extern int QRspec_maximumWords(QRencodeMode mode, int version);
|
||||
|
||||
/******************************************************************************
|
||||
* Error correction code
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return an array of ECC specification.
|
||||
* @param version version of the symbol
|
||||
* @param level error correction level
|
||||
* @param spec an array of ECC specification contains as following:
|
||||
* {# of type1 blocks, # of data code, # of ecc code,
|
||||
* # of type2 blocks, # of data code}
|
||||
*/
|
||||
void QRspec_getEccSpec(int version, QRecLevel level, int spec[5]);
|
||||
|
||||
#define QRspec_rsBlockNum(__spec__) (__spec__[0] + __spec__[3])
|
||||
#define QRspec_rsBlockNum1(__spec__) (__spec__[0])
|
||||
#define QRspec_rsDataCodes1(__spec__) (__spec__[1])
|
||||
#define QRspec_rsEccCodes1(__spec__) (__spec__[2])
|
||||
#define QRspec_rsBlockNum2(__spec__) (__spec__[3])
|
||||
#define QRspec_rsDataCodes2(__spec__) (__spec__[4])
|
||||
#define QRspec_rsEccCodes2(__spec__) (__spec__[2])
|
||||
|
||||
#define QRspec_rsDataLength(__spec__) \
|
||||
((QRspec_rsBlockNum1(__spec__) * QRspec_rsDataCodes1(__spec__)) + \
|
||||
(QRspec_rsBlockNum2(__spec__) * QRspec_rsDataCodes2(__spec__)))
|
||||
#define QRspec_rsEccLength(__spec__) \
|
||||
(QRspec_rsBlockNum(__spec__) * QRspec_rsEccCodes1(__spec__))
|
||||
|
||||
/******************************************************************************
|
||||
* Version information pattern
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return BCH encoded version information pattern that is used for the symbol
|
||||
* of version 7 or greater. Use lower 18 bits.
|
||||
* @param version version of the symbol
|
||||
* @return BCH encoded version information pattern
|
||||
*/
|
||||
extern unsigned int QRspec_getVersionPattern(int version);
|
||||
|
||||
/******************************************************************************
|
||||
* Format information
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return BCH encoded format information pattern.
|
||||
* @param mask mask number
|
||||
* @param level error correction level
|
||||
* @return BCH encoded format information pattern
|
||||
*/
|
||||
extern unsigned int QRspec_getFormatInfo(int mask, QRecLevel level);
|
||||
|
||||
/******************************************************************************
|
||||
* Frame
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return a copy of initialized frame.
|
||||
* @param version version of the symbol
|
||||
* @return Array of unsigned char. You can free it by free().
|
||||
*/
|
||||
extern unsigned char *QRspec_newFrame(int version);
|
||||
|
||||
/******************************************************************************
|
||||
* Mode indicator
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Mode indicator. See Table 2 of JIS X0510:2004, pp.16.
|
||||
*/
|
||||
#define QRSPEC_MODEID_ECI 7
|
||||
#define QRSPEC_MODEID_NUM 1
|
||||
#define QRSPEC_MODEID_AN 2
|
||||
#define QRSPEC_MODEID_8 4
|
||||
#define QRSPEC_MODEID_KANJI 8
|
||||
#define QRSPEC_MODEID_FNC1FIRST 5
|
||||
#define QRSPEC_MODEID_FNC1SECOND 9
|
||||
#define QRSPEC_MODEID_STRUCTURE 3
|
||||
#define QRSPEC_MODEID_TERMINATOR 0
|
||||
|
||||
#endif /* QRSPEC_H */
|