mirror of
https://github.com/zhuzichu520/FluentUI.git
synced 2025-07-06 02:15:23 +08:00
Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
4b84e9175d | |||
475cb54d73 | |||
b0edf23f33 | |||
c123db97b7 | |||
1450016c69 | |||
6221eb4178 | |||
42f0987e73 | |||
99ff310448 | |||
bf5c722058 | |||
8253fb611f | |||
0b0fbe1e64 | |||
2d1957afe3 | |||
823721ab8c | |||
bf074da658 | |||
91a692484f | |||
46f7299362 | |||
9f652a7c76 | |||
9adb6b645b | |||
2cfc73c00b | |||
d817782526 | |||
9dd9d10049 | |||
fa6b5cfc45 | |||
217ceabbaa | |||
83a66b3f15 | |||
3239e6f12c | |||
1c67f2a41b | |||
0b7358af41 | |||
a851696eb0 | |||
f6cc83123b |
6
.github/workflows/macos.yml
vendored
6
.github/workflows/macos.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-13]
|
||||
qt_ver: [6.6.0]
|
||||
qt_ver: [6.6.1]
|
||||
qt_arch: [clang_64]
|
||||
env:
|
||||
targetName: example
|
||||
@ -50,11 +50,13 @@ jobs:
|
||||
cmake --version
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=/Users/runner/work/FluentUI/Qt/6.6.0/macos -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release -GNinja ..
|
||||
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=/Users/runner/work/FluentUI/Qt/6.6.1/macos -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Release -GNinja ..
|
||||
cmake --build . --target all --config Release --parallel
|
||||
|
||||
- name: package
|
||||
run: |
|
||||
# 先删除所有dSYM文件,减少包的体积
|
||||
sudo find /Users/runner/work/FluentUI/Qt/6.6.1/macos/qml -name "*.dSYM" | xargs rm -r
|
||||
# 拷贝依赖
|
||||
sudo macdeployqt bin/release/${targetName}.app -qmldir=. -dmg
|
||||
|
||||
|
4
.github/workflows/ubuntu.yml
vendored
4
.github/workflows/ubuntu.yml
vendored
@ -23,7 +23,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04]
|
||||
qt_ver: [6.6.0]
|
||||
qt_ver: [6.6.1]
|
||||
qt_arch: [gcc_64]
|
||||
env:
|
||||
targetName: example
|
||||
@ -55,7 +55,7 @@ jobs:
|
||||
cmake --version
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=/home/runner/work/FluentUI/Qt/6.6.0/gcc_64 -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release -GNinja ..
|
||||
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=/home/runner/work/FluentUI/Qt/6.6.1/gcc_64 -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release -GNinja ..
|
||||
cmake --build . --target all --config Release --parallel
|
||||
|
||||
- name: install QT linux deploy
|
||||
|
4
.github/workflows/windows-mingw.yml
vendored
4
.github/workflows/windows-mingw.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
||||
os: [windows-2022]
|
||||
include:
|
||||
- qt_arch: win64_mingw
|
||||
qt_ver: 6.6.0
|
||||
qt_ver: 6.6.1
|
||||
qt_tools: "tools_mingw,9.0.0-1-202203221220,qt.tools.win64_mingw900"
|
||||
qt_tools_mingw_install: mingw900_64
|
||||
env:
|
||||
@ -69,7 +69,7 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
ninja --version
|
||||
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=D:\a\FluentUI\Qt\6.6.0\mingw_64 -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release -GNinja ..
|
||||
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=D:\a\FluentUI\Qt\6.6.1\mingw_64 -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release -GNinja ..
|
||||
cmake --build . --target all --config Release --parallel
|
||||
|
||||
- name: package
|
||||
|
4
.github/workflows/windows.yml
vendored
4
.github/workflows/windows.yml
vendored
@ -23,7 +23,7 @@ jobs:
|
||||
matrix:
|
||||
os: [windows-2019]
|
||||
include:
|
||||
- qt_ver: 6.6.0
|
||||
- qt_ver: 6.6.1
|
||||
qt_arch: win64_msvc2019_64
|
||||
msvc_arch: x64
|
||||
qt_arch_install: msvc2019_64
|
||||
@ -52,7 +52,7 @@ jobs:
|
||||
ninja --version
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=D:\a\FluentUI\Qt\6.6.0\msvc2019_64 -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_BUILD_TYPE=Release -GNinja ..
|
||||
cmake -DCMAKE_MESSAGE_LOG_LEVEL=STATUS -DCMAKE_PREFIX_PATH=D:\a\FluentUI\Qt\6.6.1\msvc2019_64 -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_BUILD_TYPE=Release -GNinja ..
|
||||
cmake --build . --target all --config Release --parallel
|
||||
echo winSdkDir=%WindowsSdkDir% >> %GITHUB_ENV%
|
||||
echo winSdkVer=%WindowsSdkVersion% >> %GITHUB_ENV%
|
||||
|
BIN
3rdparty/Win_x86/msvc/libcrypto-1_1.dll
vendored
BIN
3rdparty/Win_x86/msvc/libcrypto-1_1.dll
vendored
Binary file not shown.
BIN
3rdparty/Win_x86/msvc/libssl-1_1.dll
vendored
BIN
3rdparty/Win_x86/msvc/libssl-1_1.dll
vendored
Binary file not shown.
@ -26,6 +26,7 @@ endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
#Release也支持日志打印代码位置
|
||||
target_compile_definitions(fluentuiplugin
|
||||
PRIVATE
|
||||
QT_MESSAGELOGCONTEXT
|
||||
|
@ -24,6 +24,7 @@ endif()
|
||||
#获取文件路径分隔符(解决执行命令的时候有些平台会报错)
|
||||
file(TO_CMAKE_PATH "/" PATH_SEPARATOR)
|
||||
|
||||
#导入Qt相关依赖包
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Quick Svg Network)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Quick Svg Network)
|
||||
|
||||
@ -51,22 +52,28 @@ endforeach(filepath)
|
||||
|
||||
if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
||||
#遍历所有qml文件
|
||||
file(GLOB_RECURSE QML_PATHS *.qml)
|
||||
file(GLOB_RECURSE QML_PATHS *.qml qmldir)
|
||||
foreach(filepath ${QML_PATHS})
|
||||
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
|
||||
if(${filepath} MATCHES "Qt${QT_VERSION_MAJOR}/")
|
||||
string(REPLACE "qml-Qt${QT_VERSION_MAJOR}" "qml" filealias ${filename})
|
||||
if(${filepath} MATCHES "qml-Qt6")
|
||||
string(REPLACE "qml-Qt6" "qml" filealias ${filename})
|
||||
set_source_files_properties(${filename} PROPERTIES QT_RESOURCE_ALIAS ${filealias})
|
||||
if(${filename} MATCHES "qmldir")
|
||||
list(APPEND resource_files ${filename})
|
||||
else()
|
||||
list(APPEND qml_files ${filename})
|
||||
endif()
|
||||
endif()
|
||||
endforeach(filepath)
|
||||
|
||||
#遍历所有资源文件
|
||||
file(GLOB_RECURSE RES_PATHS *.png *.jpg *.svg *.ico *.ttf *.webp *.obj qmldir)
|
||||
file(GLOB_RECURSE RES_PATHS *.png *.jpg *.svg *.ico *.ttf *.webp *.obj)
|
||||
foreach(filepath ${RES_PATHS})
|
||||
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" filename ${filepath})
|
||||
message(${filename})
|
||||
list(APPEND resource_files ${filename})
|
||||
endforeach(filepath)
|
||||
|
||||
endif()
|
||||
|
||||
#如果是Windows平台,则生成rc文件,还有inno setup脚本文件
|
||||
@ -95,20 +102,19 @@ else ()
|
||||
)
|
||||
endif ()
|
||||
|
||||
#复制程序运行所需要的动态库
|
||||
if(WIN32)
|
||||
#复制动态库到可执行文件同级目录下
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
set(3RDPARTY_ARCH_DIR ${CMAKE_SOURCE_DIR}/3rdparty/Win_x86)
|
||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(3RDPARTY_ARCH_DIR ${CMAKE_SOURCE_DIR}/3rdparty/Win_x64)
|
||||
endif()
|
||||
if(MSVC)
|
||||
set(DLLPATH ${3RDPARTY_ARCH_DIR}/msvc/*.dll)
|
||||
elseif(MINGW)
|
||||
set(DLLPATH ${3RDPARTY_ARCH_DIR}/mingw/*.dll)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
set(3RDPARTY_DLL_DIR ${CMAKE_SOURCE_DIR}/3rdparty/msvc/x86/*.dll)
|
||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(3RDPARTY_DLL_DIR ${CMAKE_SOURCE_DIR}/3rdparty/msvc/x64/*.dll)
|
||||
endif()
|
||||
string(REPLACE "/" ${PATH_SEPARATOR} DLLPATH "${DLLPATH}")
|
||||
file(GLOB DLL_FILES ${DLLPATH})
|
||||
elseif(MINGW)
|
||||
set(3RDPARTY_DLL_DIR ${CMAKE_SOURCE_DIR}/3rdparty/mingw/*.dll)
|
||||
endif()
|
||||
string(REPLACE "/" ${PATH_SEPARATOR} 3RDPARTY_DLL_DIR "${3RDPARTY_DLL_DIR}")
|
||||
file(GLOB DLL_FILES ${3RDPARTY_DLL_DIR})
|
||||
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${DLL_FILES}
|
||||
@ -117,7 +123,7 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
||||
#添加qml模块
|
||||
#如果是Qt6.2以上,则使用qt_add_qml_module添加资源文件
|
||||
qt_add_qml_module(example
|
||||
URI "example"
|
||||
VERSION 1.0
|
||||
@ -126,6 +132,7 @@ if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
||||
RESOURCE_PREFIX "/"
|
||||
)
|
||||
else()
|
||||
#如果是Qt6.2以下,则使用qrc添加资源文件
|
||||
target_include_directories(example PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
@ -153,11 +160,13 @@ set_target_properties(example PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
)
|
||||
|
||||
#Release也支持日志打印代码位置
|
||||
target_compile_definitions(example
|
||||
PRIVATE
|
||||
QT_MESSAGELOGCONTEXT
|
||||
)
|
||||
|
||||
#目标文件链接库
|
||||
target_link_libraries(example PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Quick
|
||||
Qt${QT_VERSION_MAJOR}::Svg
|
||||
|
@ -50,9 +50,7 @@ FluObject{
|
||||
}
|
||||
title:"Buttons"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/Button.png"
|
||||
recentlyUpdated:true
|
||||
desc:"A control that responds to user input and raisesa Click event."
|
||||
extra:({image:"qrc:/example/res/image/control/Button.png",recentlyUpdated:true,desc:"A control that responds to user input and raisesa Click event."})
|
||||
url:"qrc:/example/qml/page/T_Buttons.qml"
|
||||
onTap:{
|
||||
item_buttons.count = 0
|
||||
@ -83,18 +81,14 @@ FluObject{
|
||||
FluPaneItem{
|
||||
title:"Slider"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/Slider.png"
|
||||
recentlyUpdated:true
|
||||
desc:"A control that lets the user select from a rangeof values by moving a Thumb control along atrack."
|
||||
extra:({image:"qrc:/example/res/image/control/Slider.png",recentlyUpdated:true,desc:"A control that lets the user select from a rangeof values by moving a Thumb control along atrack."})
|
||||
url:"qrc:/example/qml/page/T_Slider.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
FluPaneItem{
|
||||
title:"CheckBox"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/Checkbox.png"
|
||||
recentlyUpdated:true
|
||||
desc:"A control that a user can select or clear."
|
||||
extra:({image:"qrc:/example/res/image/control/Checkbox.png",recentlyUpdated:true,desc:"A control that a user can select or clear."})
|
||||
url:"qrc:/example/qml/page/T_CheckBox.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
@ -164,9 +158,7 @@ FluObject{
|
||||
FluPaneItem{
|
||||
title:"InfoBar"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/InfoBar.png"
|
||||
recentlyUpdated:true
|
||||
desc:"An inline message to display app-wide statuschange information."
|
||||
extra:({image:"qrc:/example/res/image/control/InfoBar.png",recentlyUpdated:true,desc:"An inline message to display app-wide statuschange information."})
|
||||
url:"qrc:/example/qml/page/T_InfoBar.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
@ -276,10 +268,7 @@ FluObject{
|
||||
FluPaneItem{
|
||||
title:"Pivot"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/Pivot.png"
|
||||
recentlyAdded:true
|
||||
order:3
|
||||
desc:"Presents information from different sources in atabbed view."
|
||||
extra:({image:"qrc:/example/res/image/control/Pivot.png",order:3,recentlyAdded:true,desc:"Presents information from different sources in atabbed view."})
|
||||
url:"qrc:/example/qml/page/T_Pivot.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
@ -292,10 +281,7 @@ FluObject{
|
||||
FluPaneItem{
|
||||
title:"TabView"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/TabView.png"
|
||||
recentlyAdded:true
|
||||
order:1
|
||||
desc:"A control that displays a collection of tabs thatcan be used to display several documents."
|
||||
extra:({image:"qrc:/example/res/image/control/TabView.png",order:1,recentlyAdded:true,desc:"A control that displays a collection of tabs thatcan be used to display several documents."})
|
||||
url:"qrc:/example/qml/page/T_TabView.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
@ -308,10 +294,7 @@ FluObject{
|
||||
FluPaneItem{
|
||||
title:"TableView"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/DataGrid.png"
|
||||
recentlyAdded:true
|
||||
order:4
|
||||
desc:"The TableView control provides a flexible way to display a collection of data in rows and columns"
|
||||
extra:({image:"qrc:/example/res/image/control/DataGrid.png",order:4,recentlyAdded:true,desc:"The TableView control provides a flexible way to display a collection of data in rows and columns"})
|
||||
url:"qrc:/example/qml/page/T_TableView.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
@ -330,10 +313,7 @@ FluObject{
|
||||
FluPaneItem{
|
||||
title:"FlipView"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/FlipView.png"
|
||||
recentlyAdded:true
|
||||
order:2
|
||||
desc:"Presents a collection of items that the user canflip through, one item at a time."
|
||||
extra:({image:"qrc:/example/res/image/control/FlipView.png",order:2,recentlyAdded:true,desc:"Presents a collection of items that the user canflip through, one item at a time."})
|
||||
url:"qrc:/example/qml/page/T_FlipView.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
@ -490,21 +470,14 @@ FluObject{
|
||||
|
||||
function getRecentlyAddedData(){
|
||||
var arr = []
|
||||
for(var i=0;i<children.length;i++){
|
||||
var item = children[i]
|
||||
if(item instanceof FluPaneItem && item.recentlyAdded){
|
||||
var items = navigationView.getItems();
|
||||
for(var i=0;i<items.length;i++){
|
||||
var item = items[i]
|
||||
if(item instanceof FluPaneItem && item.extra && item.extra.recentlyAdded){
|
||||
arr.push(item)
|
||||
}
|
||||
if(item instanceof FluPaneItemExpander){
|
||||
for(var j=0;j<item.children.length;j++){
|
||||
var itemChild = item.children[j]
|
||||
if(itemChild instanceof FluPaneItem && itemChild.recentlyAdded){
|
||||
arr.push(itemChild)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
arr.sort(function(o1,o2){ return o2.order-o1.order })
|
||||
arr.sort(function(o1,o2){ return o2.extra.order-o1.extra.order })
|
||||
return arr
|
||||
}
|
||||
|
||||
@ -513,7 +486,7 @@ FluObject{
|
||||
var items = navigationView.getItems();
|
||||
for(var i=0;i<items.length;i++){
|
||||
var item = items[i]
|
||||
if(item instanceof FluPaneItem && item.recentlyUpdated){
|
||||
if(item instanceof FluPaneItem && item.extra && item.extra.recentlyUpdated){
|
||||
arr.push(item)
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ FluScrollablePage{
|
||||
Component{
|
||||
id:com_item
|
||||
Item{
|
||||
property string desc: modelData.desc
|
||||
property string desc: modelData.extra.desc
|
||||
width: 320
|
||||
height: 120
|
||||
FluArea{
|
||||
@ -182,7 +182,7 @@ FluScrollablePage{
|
||||
id:item_icon
|
||||
height: 40
|
||||
width: 40
|
||||
source: modelData.image
|
||||
source: modelData.extra.image
|
||||
anchors{
|
||||
left: parent.left
|
||||
leftMargin: 20
|
||||
|
@ -87,26 +87,6 @@ FluScrollablePage{
|
||||
}
|
||||
}
|
||||
|
||||
FluArea{
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 20
|
||||
height: 50
|
||||
paddings: 10
|
||||
FluCheckBox{
|
||||
text:"Software Render"
|
||||
checked: SettingsHelper.getRender() === "software"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClicked: {
|
||||
if(SettingsHelper.getRender() === "software"){
|
||||
SettingsHelper.saveRender("")
|
||||
}else{
|
||||
SettingsHelper.saveRender("software")
|
||||
}
|
||||
dialog_restart.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FluContentDialog{
|
||||
id:dialog_restart
|
||||
title:"友情提示"
|
||||
|
@ -9,7 +9,7 @@ FluWindow {
|
||||
id:window
|
||||
title:"关于"
|
||||
width: 600
|
||||
height: 600
|
||||
height: 580
|
||||
fixSize: true
|
||||
launchMode: FluWindowType.SingleTask
|
||||
|
||||
|
@ -50,9 +50,7 @@ FluObject{
|
||||
}
|
||||
title:"Buttons"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/Button.png"
|
||||
recentlyUpdated:true
|
||||
desc:"A control that responds to user input and raisesa Click event."
|
||||
extra:({image:"qrc:/example/res/image/control/Button.png",recentlyUpdated:true,desc:"A control that responds to user input and raisesa Click event."})
|
||||
url:"qrc:/example/qml/page/T_Buttons.qml"
|
||||
onTap:{
|
||||
item_buttons.count = 0
|
||||
@ -83,18 +81,14 @@ FluObject{
|
||||
FluPaneItem{
|
||||
title:"Slider"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/Slider.png"
|
||||
recentlyUpdated:true
|
||||
desc:"A control that lets the user select from a rangeof values by moving a Thumb control along atrack."
|
||||
extra:({image:"qrc:/example/res/image/control/Slider.png",recentlyUpdated:true,desc:"A control that lets the user select from a rangeof values by moving a Thumb control along atrack."})
|
||||
url:"qrc:/example/qml/page/T_Slider.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
FluPaneItem{
|
||||
title:"CheckBox"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/Checkbox.png"
|
||||
recentlyUpdated:true
|
||||
desc:"A control that a user can select or clear."
|
||||
extra:({image:"qrc:/example/res/image/control/Checkbox.png",recentlyUpdated:true,desc:"A control that a user can select or clear."})
|
||||
url:"qrc:/example/qml/page/T_CheckBox.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
@ -164,9 +158,7 @@ FluObject{
|
||||
FluPaneItem{
|
||||
title:"InfoBar"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/InfoBar.png"
|
||||
recentlyUpdated:true
|
||||
desc:"An inline message to display app-wide statuschange information."
|
||||
extra:({image:"qrc:/example/res/image/control/InfoBar.png",recentlyUpdated:true,desc:"An inline message to display app-wide statuschange information."})
|
||||
url:"qrc:/example/qml/page/T_InfoBar.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
@ -276,10 +268,7 @@ FluObject{
|
||||
FluPaneItem{
|
||||
title:"Pivot"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/Pivot.png"
|
||||
recentlyAdded:true
|
||||
order:3
|
||||
desc:"Presents information from different sources in atabbed view."
|
||||
extra:({image:"qrc:/example/res/image/control/Pivot.png",order:3,recentlyAdded:true,desc:"Presents information from different sources in atabbed view."})
|
||||
url:"qrc:/example/qml/page/T_Pivot.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
@ -292,10 +281,7 @@ FluObject{
|
||||
FluPaneItem{
|
||||
title:"TabView"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/TabView.png"
|
||||
recentlyAdded:true
|
||||
order:1
|
||||
desc:"A control that displays a collection of tabs thatcan be used to display several documents."
|
||||
extra:({image:"qrc:/example/res/image/control/TabView.png",order:1,recentlyAdded:true,desc:"A control that displays a collection of tabs thatcan be used to display several documents."})
|
||||
url:"qrc:/example/qml/page/T_TabView.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
@ -308,10 +294,7 @@ FluObject{
|
||||
FluPaneItem{
|
||||
title:"TableView"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/DataGrid.png"
|
||||
recentlyAdded:true
|
||||
order:4
|
||||
desc:"The TableView control provides a flexible way to display a collection of data in rows and columns"
|
||||
extra:({image:"qrc:/example/res/image/control/DataGrid.png",order:4,recentlyAdded:true,desc:"The TableView control provides a flexible way to display a collection of data in rows and columns"})
|
||||
url:"qrc:/example/qml/page/T_TableView.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
@ -330,10 +313,7 @@ FluObject{
|
||||
FluPaneItem{
|
||||
title:"FlipView"
|
||||
menuDelegate: paneItemMenu
|
||||
image:"qrc:/example/res/image/control/FlipView.png"
|
||||
recentlyAdded:true
|
||||
order:2
|
||||
desc:"Presents a collection of items that the user canflip through, one item at a time."
|
||||
extra:({image:"qrc:/example/res/image/control/FlipView.png",order:2,recentlyAdded:true,desc:"Presents a collection of items that the user canflip through, one item at a time."})
|
||||
url:"qrc:/example/qml/page/T_FlipView.qml"
|
||||
onTap:{ navigationView.push(url) }
|
||||
}
|
||||
@ -490,21 +470,14 @@ FluObject{
|
||||
|
||||
function getRecentlyAddedData(){
|
||||
var arr = []
|
||||
for(var i=0;i<children.length;i++){
|
||||
var item = children[i]
|
||||
if(item instanceof FluPaneItem && item.recentlyAdded){
|
||||
var items = navigationView.getItems();
|
||||
for(var i=0;i<items.length;i++){
|
||||
var item = items[i]
|
||||
if(item instanceof FluPaneItem && item.extra && item.extra.recentlyAdded){
|
||||
arr.push(item)
|
||||
}
|
||||
if(item instanceof FluPaneItemExpander){
|
||||
for(var j=0;j<item.children.length;j++){
|
||||
var itemChild = item.children[j]
|
||||
if(itemChild instanceof FluPaneItem && itemChild.recentlyAdded){
|
||||
arr.push(itemChild)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
arr.sort(function(o1,o2){ return o2.order-o1.order })
|
||||
arr.sort(function(o1,o2){ return o2.extra.order-o1.extra.order })
|
||||
return arr
|
||||
}
|
||||
|
||||
@ -513,7 +486,7 @@ FluObject{
|
||||
var items = navigationView.getItems();
|
||||
for(var i=0;i<items.length;i++){
|
||||
var item = items[i]
|
||||
if(item instanceof FluPaneItem && item.recentlyUpdated){
|
||||
if(item instanceof FluPaneItem && item.extra && item.extra.recentlyUpdated){
|
||||
arr.push(item)
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ FluScrollablePage{
|
||||
Component{
|
||||
id:com_item
|
||||
Item{
|
||||
property string desc: modelData.desc
|
||||
property string desc: modelData.extra.desc
|
||||
width: 320
|
||||
height: 120
|
||||
FluArea{
|
||||
@ -182,7 +182,7 @@ FluScrollablePage{
|
||||
id:item_icon
|
||||
height: 40
|
||||
width: 40
|
||||
source: modelData.image
|
||||
source: modelData.extra.image
|
||||
anchors{
|
||||
left: parent.left
|
||||
leftMargin: 20
|
||||
|
@ -90,26 +90,6 @@ FluScrollablePage{
|
||||
}
|
||||
}
|
||||
|
||||
FluArea{
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 20
|
||||
height: 50
|
||||
paddings: 10
|
||||
FluCheckBox{
|
||||
text:"Software Render"
|
||||
checked: SettingsHelper.getRender() === "software"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClicked: {
|
||||
if(SettingsHelper.getRender() === "software"){
|
||||
SettingsHelper.saveRender("")
|
||||
}else{
|
||||
SettingsHelper.saveRender("software")
|
||||
}
|
||||
dialog_restart.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FluContentDialog{
|
||||
id:dialog_restart
|
||||
title:"友情提示"
|
||||
|
@ -10,7 +10,7 @@ FluWindow {
|
||||
id:window
|
||||
title:"关于"
|
||||
width: 600
|
||||
height: 600
|
||||
height: 580
|
||||
fixSize: true
|
||||
launchMode: FluWindowType.SingleTask
|
||||
|
||||
|
@ -10,7 +10,3 @@ AppInfo::AppInfo(QObject *parent)
|
||||
{
|
||||
version(APPLICATION_VERSION);
|
||||
}
|
||||
|
||||
void AppInfo::init(QQmlApplicationEngine *engine){
|
||||
engine->rootContext();
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ private:
|
||||
explicit AppInfo(QObject *parent = nullptr);
|
||||
public:
|
||||
SINGLETONG(AppInfo)
|
||||
void init(QQmlApplicationEngine *engine);
|
||||
};
|
||||
|
||||
#endif // APPINFO_H
|
||||
|
@ -94,6 +94,9 @@ QString Log::prettyProductInfoWrapper()
|
||||
|
||||
static inline void myMessageHandler(const QtMsgType type, const QMessageLogContext &context, const QString &message)
|
||||
{
|
||||
if(message == "Could not get the INetworkConnection instance for the adapter GUID."){
|
||||
return;
|
||||
}
|
||||
if(logLevelMap[type]>g_logLevel){
|
||||
return;
|
||||
}
|
||||
@ -165,12 +168,13 @@ static inline void myMessageHandler(const QtMsgType type, const QMessageLogConte
|
||||
}
|
||||
}
|
||||
|
||||
void Log::setup(const QString &app)
|
||||
void Log::setup(const QString &app,int level)
|
||||
{
|
||||
Q_ASSERT(!app.isEmpty());
|
||||
if (app.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
g_logLevel = level;
|
||||
static bool once = false;
|
||||
if (once) {
|
||||
return;
|
||||
|
@ -5,7 +5,7 @@
|
||||
namespace Log
|
||||
{
|
||||
QString prettyProductInfoWrapper();
|
||||
void setup(const QString &app);
|
||||
void setup(const QString &app,int level = 4);
|
||||
}
|
||||
|
||||
#endif // LOG_H
|
||||
|
@ -19,8 +19,6 @@ public:
|
||||
SINGLETONG(SettingsHelper)
|
||||
~SettingsHelper() override;
|
||||
void init(char *argv[]);
|
||||
Q_INVOKABLE void saveRender(const QVariant& render){save("render",render);}
|
||||
Q_INVOKABLE QString getRender(){return get("render").toString();}
|
||||
Q_INVOKABLE void saveDarkMode(int darkModel){save("darkMode",darkModel);}
|
||||
Q_INVOKABLE int getDarkMode(){return get("darkMode",QVariant(0)).toInt();}
|
||||
Q_INVOKABLE void saveUseSystemAppBar(bool useSystemAppBar){save("useSystemAppBar",useSystemAppBar);}
|
||||
|
@ -43,18 +43,8 @@ int main(int argc, char *argv[])
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
#endif
|
||||
#endif
|
||||
if(SettingsHelper::getInstance()->getRender()=="software"){
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
QQuickWindow::setGraphicsApi(QSGRendererInterface::Software);
|
||||
#elif (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Software);
|
||||
#endif
|
||||
}
|
||||
QGuiApplication app(argc, argv);
|
||||
// QLoggingCategory::setFilterRules(QStringLiteral("qt.scenegraph.general=true"));
|
||||
// qSetMessagePattern("%{category}: %{message}");
|
||||
QQmlApplicationEngine engine;
|
||||
AppInfo::getInstance()->init(&engine);
|
||||
engine.rootContext()->setContextProperty("AppInfo",AppInfo::getInstance());
|
||||
engine.rootContext()->setContextProperty("SettingsHelper",SettingsHelper::getInstance());
|
||||
#ifdef FLUENTUI_BUILD_STATIC_LIB
|
||||
|
@ -44,4 +44,10 @@ private: \
|
||||
return Singleton<Class>::getInstance(); \
|
||||
}
|
||||
|
||||
#define HIDE_CONSTRUCTOR(Class) \
|
||||
private: \
|
||||
Class() = default; \
|
||||
Class(const Class& other) = delete; \
|
||||
Class& operator=(const Class& other) = delete;
|
||||
|
||||
#endif // SINGLETON_H
|
||||
|
@ -14,6 +14,7 @@ if (FLUENTUI_BUILD_STATIC_LIB)
|
||||
add_definitions(-DFLUENTUI_BUILD_STATIC_LIB)
|
||||
endif()
|
||||
|
||||
#导入Qt相关依赖包
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Quick Qml)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Quick Qml)
|
||||
|
||||
@ -64,7 +65,6 @@ if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
#添加qml模块
|
||||
if (FLUENTUI_BUILD_STATIC_LIB)
|
||||
set(LIB_TYPE "STATIC")
|
||||
else()
|
||||
@ -89,6 +89,7 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
||||
#如果是Qt6.2版本以上,则使用qt_add_library,qt_add_qml_module函数添加资源文件
|
||||
if(FLUENTUI_BUILD_STATIC_LIB)
|
||||
set(FLUENTUI_QML_PLUGIN_DIRECTORY ${CMAKE_BINARY_DIR}/FluentUI)
|
||||
endif()
|
||||
@ -106,6 +107,7 @@ if(QT_VERSION VERSION_GREATER_EQUAL "6.2")
|
||||
RESOURCE_PREFIX "/qt/qml"
|
||||
)
|
||||
else()
|
||||
#如果是Qt6.2版本以下,则使用add_qmlplugin函数添加资源文件,这是个自定义的函数,详情见.cmake/QmlPlugin.cmake
|
||||
include(QmlPlugin)
|
||||
add_qmlplugin(${PROJECT_NAME}
|
||||
URI "FluentUI"
|
||||
@ -120,6 +122,7 @@ endif()
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
#导入qrcode配置文件
|
||||
HAVE_CONFIG_H
|
||||
)
|
||||
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
void removeWindow(QQuickWindow* window);
|
||||
private:
|
||||
QMap<quint64, QQuickWindow*> _windows;
|
||||
QObject* _application;
|
||||
QObject* _application = nullptr;
|
||||
};
|
||||
|
||||
#endif // FLUAPP_H
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define FLUCOLORSET_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QtQml/qqml.h>
|
||||
#include "stdafx.h"
|
||||
|
||||
/**
|
||||
@ -17,6 +18,7 @@ class FluColorSet : public QObject
|
||||
Q_PROPERTY_AUTO(QString,light)
|
||||
Q_PROPERTY_AUTO(QString,lighter)
|
||||
Q_PROPERTY_AUTO(QString,lightest)
|
||||
QML_NAMED_ELEMENT(FluColorSet)
|
||||
public:
|
||||
explicit FluColorSet(QObject *parent = nullptr);
|
||||
};
|
||||
|
@ -27,7 +27,7 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
Grey210("#161514");
|
||||
Grey220("#11100f");
|
||||
|
||||
FluColorSet *yellow = new FluColorSet();
|
||||
FluColorSet *yellow = new FluColorSet(this);
|
||||
yellow->darkest("#f9a825");
|
||||
yellow->darker("#fbc02d");
|
||||
yellow->dark("#fdd435");
|
||||
@ -37,7 +37,7 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
yellow->lightest("#fff59b");
|
||||
Yellow(yellow);
|
||||
|
||||
FluColorSet *orange = new FluColorSet();
|
||||
FluColorSet *orange = new FluColorSet(this);
|
||||
orange->darkest("#993d07");
|
||||
orange->darker("#ac4408");
|
||||
orange->dark("#d1580a");
|
||||
@ -47,7 +47,7 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
orange->lightest("#fac06a");
|
||||
Orange(orange);
|
||||
|
||||
FluColorSet *red = new FluColorSet();
|
||||
FluColorSet *red = new FluColorSet(this);
|
||||
red->darkest("#8f0a15");
|
||||
red->darker("#a20b18");
|
||||
red->dark("#b90d1c");
|
||||
@ -57,7 +57,7 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
red->lightest("#f06b76");
|
||||
Red(red);
|
||||
|
||||
FluColorSet *magenta = new FluColorSet();
|
||||
FluColorSet *magenta = new FluColorSet(this);
|
||||
magenta->darkest("#6f004f");
|
||||
magenta->darker("#a0076c");
|
||||
magenta->dark("#b50d7d");
|
||||
@ -67,7 +67,7 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
magenta->lightest("#f18cd5");
|
||||
Magenta(magenta);
|
||||
|
||||
FluColorSet *purple = new FluColorSet();
|
||||
FluColorSet *purple = new FluColorSet(this);
|
||||
purple->darkest("#2c0f76");
|
||||
purple->darker("#3d0f99");
|
||||
purple->dark("#4e11ae");
|
||||
@ -77,7 +77,7 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
purple->lightest("#9e8ed9");
|
||||
Purple(purple);
|
||||
|
||||
FluColorSet *blue = new FluColorSet();
|
||||
FluColorSet *blue = new FluColorSet(this);
|
||||
blue->darkest("#004A83");
|
||||
blue->darker("#005494");
|
||||
blue->dark("#0066B4");
|
||||
@ -87,7 +87,7 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
blue->lightest("#60ABE4");
|
||||
Blue(blue);
|
||||
|
||||
FluColorSet *teal = new FluColorSet();
|
||||
FluColorSet *teal = new FluColorSet(this);
|
||||
teal->darkest("#006E5B");
|
||||
teal->darker("#007C67");
|
||||
teal->dark("#00977D");
|
||||
@ -97,7 +97,7 @@ FluColors::FluColors(QObject *parent):QObject{parent}{
|
||||
teal->lightest("#60CFBC");
|
||||
Teal(teal);
|
||||
|
||||
FluColorSet *green = new FluColorSet();
|
||||
FluColorSet *green = new FluColorSet(this);
|
||||
green->darkest("#094C09");
|
||||
green->darker("#0C5D0C");
|
||||
green->dark("#0E6F0E");
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "FluFramelessHelper.h"
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QOperatingSystemVersion>
|
||||
#include "FluTools.h"
|
||||
#ifdef Q_OS_WIN
|
||||
#pragma comment (lib,"user32.lib")
|
||||
#pragma comment (lib,"dwmapi.lib")
|
||||
@ -13,6 +13,34 @@ static inline QByteArray qtNativeEventType()
|
||||
static const auto result = "windows_generic_MSG";
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline bool isTaskbarAutoHide() {
|
||||
APPBARDATA appBarData;
|
||||
memset(&appBarData, 0, sizeof(appBarData));
|
||||
appBarData.cbSize = sizeof(appBarData);
|
||||
appBarData.hWnd = FindWindowW(L"Shell_TrayWnd", NULL);
|
||||
LPARAM lParam = SHAppBarMessage(ABM_GETSTATE, &appBarData);
|
||||
return lParam & ABS_AUTOHIDE;
|
||||
}
|
||||
|
||||
static inline QColor getAccentColor(){
|
||||
typedef HRESULT (WINAPI* DwmGetColorizationColorPtr)(DWORD* pcrColorization,BOOL* pfOpaqueBlend);
|
||||
HMODULE module = LoadLibraryW(L"dwmapi.dll");
|
||||
if (module)
|
||||
{
|
||||
DwmGetColorizationColorPtr dwm_get_colorization_color;
|
||||
dwm_get_colorization_color= reinterpret_cast<DwmGetColorizationColorPtr>(GetProcAddress(module, "DwmGetColorizationColor"));
|
||||
DWORD color = 0;
|
||||
BOOL bOpaque = FALSE;
|
||||
if (dwm_get_colorization_color)
|
||||
{
|
||||
dwm_get_colorization_color(&color,&bOpaque);
|
||||
}
|
||||
return QColor(color);
|
||||
}
|
||||
return QColor();
|
||||
}
|
||||
|
||||
static inline bool isCompositionEnabled(){
|
||||
typedef HRESULT (WINAPI* DwmIsCompositionEnabledPtr)(BOOL *pfEnabled);
|
||||
HMODULE module = LoadLibraryW(L"dwmapi.dll");
|
||||
@ -31,8 +59,7 @@ static inline bool isCompositionEnabled(){
|
||||
}
|
||||
|
||||
static inline void showShadow(HWND hwnd){
|
||||
if(isCompositionEnabled()){
|
||||
const MARGINS shadow = { 1, 1, 1, 1 };
|
||||
const MARGINS shadow = { 0, 0, 1, 0 };
|
||||
typedef HRESULT (WINAPI* DwmExtendFrameIntoClientAreaPtr)(HWND hWnd, const MARGINS *pMarInset);
|
||||
HMODULE module = LoadLibraryW(L"dwmapi.dll");
|
||||
if (module)
|
||||
@ -44,22 +71,18 @@ static inline void showShadow(HWND hwnd){
|
||||
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();
|
||||
FramelessEventFilter::FramelessEventFilter(FluFramelessHelper* helper){
|
||||
_helper = helper;
|
||||
_current = _helper->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) {
|
||||
if ((eventType != qtNativeEventType()) || !message || _helper.isNull() || _helper->window.isNull()) {
|
||||
return false;
|
||||
}
|
||||
const auto msg = static_cast<const MSG *>(message);
|
||||
@ -72,12 +95,12 @@ bool FramelessEventFilter::nativeEventFilter(const QByteArray &eventType, void *
|
||||
return false;
|
||||
}
|
||||
const UINT uMsg = msg->message;
|
||||
const WPARAM wParam = msg->wParam;
|
||||
const LPARAM lParam = msg->lParam;
|
||||
if (!msg || !hwnd)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const WPARAM wParam = msg->wParam;
|
||||
const LPARAM lParam = msg->lParam;
|
||||
if(uMsg == WM_WINDOWPOSCHANGING){
|
||||
WINDOWPOS* wp = reinterpret_cast<WINDOWPOS*>(lParam);
|
||||
if (wp != nullptr && (wp->flags & SWP_NOSIZE) == 0)
|
||||
@ -88,20 +111,46 @@ bool FramelessEventFilter::nativeEventFilter(const QByteArray &eventType, void *
|
||||
}
|
||||
return false;
|
||||
}else if(uMsg == WM_NCCALCSIZE){
|
||||
const auto clientRect = ((wParam == FALSE) ? reinterpret_cast<LPRECT>(lParam) : &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam))->rgrc[0]);
|
||||
const LONG originalTop = clientRect->top;
|
||||
const LONG originalLeft = clientRect->left;
|
||||
const LRESULT hitTestResult = ::DefWindowProcW(hwnd, WM_NCCALCSIZE, wParam, lParam);
|
||||
if ((hitTestResult != HTERROR) && (hitTestResult != HTNOWHERE)) {
|
||||
*result = hitTestResult;
|
||||
return true;
|
||||
}
|
||||
if(IsZoomed(hwnd)){
|
||||
_helper->setOriginalPos(QPoint(originalLeft,originalTop));
|
||||
if(isTaskbarAutoHide()){
|
||||
clientRect->bottom -= 1;
|
||||
}
|
||||
}else{
|
||||
_helper->setOriginalPos({});
|
||||
}
|
||||
clientRect->top = originalTop;
|
||||
*result = WVR_REDRAW;
|
||||
return true;
|
||||
}else if(uMsg == WM_NCPAINT){
|
||||
if(!isCompositionEnabled()){
|
||||
*result = WVR_REDRAW;
|
||||
}if(uMsg == WM_NCHITTEST){
|
||||
if(FluTools::getInstance()->isWindows11OrGreater() && _helper->hoverMaxBtn() && _helper->resizeable()){
|
||||
if (*result == HTNOWHERE) {
|
||||
*result = HTZOOM;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}else if(uMsg == WM_NCACTIVATE){
|
||||
if(!isCompositionEnabled()){
|
||||
*result = 1;
|
||||
}else if(uMsg == WM_NCLBUTTONDBLCLK || uMsg == WM_NCLBUTTONDOWN){
|
||||
if(FluTools::getInstance()->isWindows11OrGreater() && _helper->hoverMaxBtn() && _helper->resizeable()){
|
||||
QMouseEvent event = QMouseEvent(QEvent::MouseButtonPress, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
||||
QGuiApplication::sendEvent(_helper->maximizeButton(),&event);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}else if(uMsg == WM_NCLBUTTONUP || uMsg == WM_NCRBUTTONUP){
|
||||
if(FluTools::getInstance()->isWindows11OrGreater() && _helper->hoverMaxBtn() && _helper->resizeable()){
|
||||
QMouseEvent event = QMouseEvent(QEvent::MouseButtonRelease, QPoint(), QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
||||
QGuiApplication::sendEvent(_helper->maximizeButton(),&event);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
@ -111,56 +160,60 @@ bool FramelessEventFilter::nativeEventFilter(const QByteArray &eventType, void *
|
||||
FluFramelessHelper::FluFramelessHelper(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void FluFramelessHelper::classBegin(){
|
||||
}
|
||||
|
||||
void FluFramelessHelper::updateCursor(int edges){
|
||||
void FluFramelessHelper::_updateCursor(int edges){
|
||||
switch (edges) {
|
||||
case 0:
|
||||
_window->setCursor(Qt::ArrowCursor);
|
||||
window->setCursor(Qt::ArrowCursor);
|
||||
break;
|
||||
case Qt::LeftEdge:
|
||||
case Qt::RightEdge:
|
||||
_window->setCursor(Qt::SizeHorCursor);
|
||||
window->setCursor(Qt::SizeHorCursor);
|
||||
break;
|
||||
case Qt::TopEdge:
|
||||
case Qt::BottomEdge:
|
||||
_window->setCursor(Qt::SizeVerCursor);
|
||||
window->setCursor(Qt::SizeVerCursor);
|
||||
break;
|
||||
case Qt::LeftEdge | Qt::TopEdge:
|
||||
case Qt::RightEdge | Qt::BottomEdge:
|
||||
_window->setCursor(Qt::SizeFDiagCursor);
|
||||
window->setCursor(Qt::SizeFDiagCursor);
|
||||
break;
|
||||
case Qt::RightEdge | Qt::TopEdge:
|
||||
case Qt::LeftEdge | Qt::BottomEdge:
|
||||
_window->setCursor(Qt::SizeBDiagCursor);
|
||||
window->setCursor(Qt::SizeBDiagCursor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool FluFramelessHelper::eventFilter(QObject *obj, QEvent *ev){
|
||||
if (!_window.isNull() && _window->flags() & Qt::FramelessWindowHint) {
|
||||
if (!window.isNull() && window->flags()) {
|
||||
|
||||
static int edges = 0;
|
||||
const int margin = 8;
|
||||
switch (ev->type()) {
|
||||
case QEvent::MouseButtonPress:
|
||||
if(edges!=0){
|
||||
updateCursor(edges);
|
||||
_window->startSystemResize(Qt::Edges(edges));
|
||||
QMouseEvent *event = static_cast<QMouseEvent*>(ev);
|
||||
if(event->button() == Qt::LeftButton){
|
||||
_updateCursor(edges);
|
||||
window->startSystemResize(Qt::Edges(edges));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QEvent::MouseButtonRelease:
|
||||
edges = 0;
|
||||
updateCursor(edges);
|
||||
_updateCursor(edges);
|
||||
break;
|
||||
case QEvent::MouseMove: {
|
||||
if(_window->visibility() == QWindow::Maximized || _window->visibility() == QWindow::FullScreen){
|
||||
if(_maximized() || _fullScreen()){
|
||||
break;
|
||||
}
|
||||
if(_window->width() == _window->maximumWidth() && _window->width() == _window->minimumWidth() && _window->height() == _window->maximumHeight() && _window->height() == _window->minimumHeight()){
|
||||
if(!resizeable()){
|
||||
break;
|
||||
}
|
||||
QMouseEvent *event = static_cast<QMouseEvent*>(ev);
|
||||
@ -170,10 +223,10 @@ bool FluFramelessHelper::eventFilter(QObject *obj, QEvent *ev){
|
||||
#else
|
||||
event->position().toPoint();
|
||||
#endif
|
||||
if(p.x() >= margin && p.x() <= (_window->width() - margin) && p.y() >= margin && p.y() <= (_window->height() - margin)){
|
||||
if(p.x() >= margin && p.x() <= (window->width() - margin) && p.y() >= margin && p.y() <= (window->height() - margin)){
|
||||
if(edges != 0){
|
||||
edges = 0;
|
||||
updateCursor(edges);
|
||||
_updateCursor(edges);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -181,16 +234,16 @@ bool FluFramelessHelper::eventFilter(QObject *obj, QEvent *ev){
|
||||
if ( p.x() < margin ) {
|
||||
edges |= Qt::LeftEdge;
|
||||
}
|
||||
if ( p.x() > (_window->width() - margin) ) {
|
||||
if ( p.x() > (window->width() - margin) ) {
|
||||
edges |= Qt::RightEdge;
|
||||
}
|
||||
if ( p.y() < margin ) {
|
||||
edges |= Qt::TopEdge;
|
||||
}
|
||||
if ( p.y() > (_window->height() - margin) ) {
|
||||
if ( p.y() > (window->height() - margin) ) {
|
||||
edges |= Qt::BottomEdge;
|
||||
}
|
||||
updateCursor(edges);
|
||||
_updateCursor(edges);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -203,54 +256,145 @@ bool FluFramelessHelper::eventFilter(QObject *obj, QEvent *ev){
|
||||
void FluFramelessHelper::componentComplete(){
|
||||
auto o = parent();
|
||||
while (nullptr != o) {
|
||||
_window = (QQuickWindow*)o;
|
||||
window = (QQuickWindow*)o;
|
||||
o = o->parent();
|
||||
}
|
||||
if(!_window.isNull()){
|
||||
_window->setFlags(Qt::FramelessWindowHint|Qt::Window|Qt::WindowTitleHint|Qt::WindowMinMaxButtonsHint|Qt::WindowCloseButtonHint);
|
||||
if(!window.isNull()){
|
||||
_stayTop = QQmlProperty(window,"stayTop");
|
||||
_screen = QQmlProperty(window,"screen");
|
||||
_fixSize = QQmlProperty(window,"fixSize");
|
||||
_originalPos = QQmlProperty(window,"_originalPos");
|
||||
_accentColor = QQmlProperty(window,"_accentColor");
|
||||
#ifdef Q_OS_WIN
|
||||
_nativeEvent =new FramelessEventFilter(_window);
|
||||
if(isCompositionEnabled()){
|
||||
_accentColor.write(getAccentColor());
|
||||
_nativeEvent =new FramelessEventFilter(this);
|
||||
qApp->installNativeEventFilter(_nativeEvent);
|
||||
HWND hwnd = reinterpret_cast<HWND>(_window->winId());
|
||||
HWND hwnd = reinterpret_cast<HWND>(window->winId());
|
||||
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
|
||||
if(resizeable()){
|
||||
SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION);
|
||||
}else{
|
||||
SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME | WS_CAPTION);
|
||||
}
|
||||
SetWindowPos(hwnd,nullptr,0,0,0,0,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
|
||||
showShadow(hwnd);
|
||||
if(_fixSize.read().toBool()){
|
||||
window->setMaximumSize(window->size());
|
||||
window->setMinimumSize(window->size());
|
||||
}
|
||||
}else{
|
||||
window->setFlags((window->flags() & (~Qt::WindowMinMaxButtonsHint) & (~Qt::Dialog)) | Qt::FramelessWindowHint | Qt::Window);
|
||||
}
|
||||
#else
|
||||
window->setFlags((window->flags() & (~Qt::WindowMinMaxButtonsHint) & (~Qt::Dialog)) | Qt::FramelessWindowHint | Qt::Window);
|
||||
#endif
|
||||
_stayTop = QQmlProperty(_window,"stayTop");
|
||||
_onStayTopChange();
|
||||
_stayTop.connectNotifySignal(this,SLOT(_onStayTopChange()));
|
||||
_screen = QQmlProperty(_window,"screen");
|
||||
_screen.connectNotifySignal(this,SLOT(_onScreenChanged()));
|
||||
_window->installEventFilter(this);
|
||||
window->installEventFilter(this);
|
||||
}
|
||||
}
|
||||
|
||||
void FluFramelessHelper::_onScreenChanged(){
|
||||
_window->update();
|
||||
QGuiApplication::processEvents();
|
||||
#ifdef Q_OS_WIN
|
||||
HWND hwnd = reinterpret_cast<HWND>(window->winId());
|
||||
SetWindowPos(hwnd,0,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOOWNERZORDER);
|
||||
RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FluFramelessHelper::showSystemMenu(){
|
||||
#ifdef Q_OS_WIN
|
||||
QPoint point = QCursor::pos();
|
||||
HWND hwnd = reinterpret_cast<HWND>(window->winId());
|
||||
DWORD style = GetWindowLongPtr(hwnd,GWL_STYLE);
|
||||
SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX);
|
||||
const HMENU hMenu = ::GetSystemMenu(hwnd, FALSE);
|
||||
DeleteMenu(hMenu, SC_MOVE, MF_BYCOMMAND);
|
||||
DeleteMenu(hMenu, SC_SIZE, MF_BYCOMMAND);
|
||||
if(_maximized() || _fullScreen()){
|
||||
EnableMenuItem(hMenu,SC_RESTORE,MFS_ENABLED);
|
||||
}else{
|
||||
EnableMenuItem(hMenu,SC_RESTORE,MFS_DISABLED);
|
||||
}
|
||||
if(resizeable() && !_maximized() && !_fullScreen()){
|
||||
EnableMenuItem(hMenu,SC_MAXIMIZE,MFS_ENABLED);
|
||||
}else{
|
||||
EnableMenuItem(hMenu,SC_MAXIMIZE,MFS_DISABLED);
|
||||
}
|
||||
const int result = TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft() ? TPM_RIGHTALIGN : TPM_LEFTALIGN)), point.x()*window->devicePixelRatio(), point.y()*window->devicePixelRatio(), 0, hwnd, nullptr);
|
||||
if (result != FALSE) {
|
||||
PostMessageW(hwnd, WM_SYSCOMMAND, result, 0);
|
||||
}
|
||||
SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_THICKFRAME | WS_CAPTION &~ WS_SYSMENU);
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
HWND hwnd = reinterpret_cast<HWND>(window->winId());
|
||||
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);
|
||||
window->setFlag(Qt::WindowStaysOnTopHint,isStayTop);
|
||||
#endif
|
||||
}
|
||||
|
||||
FluFramelessHelper::~FluFramelessHelper(){
|
||||
if (!_window.isNull()) {
|
||||
_window->setFlags(Qt::Window);
|
||||
if (!window.isNull()) {
|
||||
window->setFlags(Qt::Window);
|
||||
#ifdef Q_OS_WIN
|
||||
if(isCompositionEnabled()){
|
||||
qApp->removeNativeEventFilter(_nativeEvent);
|
||||
delete _nativeEvent;
|
||||
}
|
||||
#endif
|
||||
_window->removeEventFilter(this);
|
||||
window->removeEventFilter(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool FluFramelessHelper::hoverMaxBtn(){
|
||||
QVariant appBar = window->property("appBar");
|
||||
if(appBar.isNull()){
|
||||
return false;
|
||||
}
|
||||
QVariant var;
|
||||
QMetaObject::invokeMethod(appBar.value<QObject*>(), "maximizeButtonHover",Q_RETURN_ARG(QVariant, var));
|
||||
if(var.isNull()){
|
||||
return false;
|
||||
}
|
||||
return var.toBool();
|
||||
}
|
||||
|
||||
QObject* FluFramelessHelper::maximizeButton(){
|
||||
QVariant appBar = window->property("appBar");
|
||||
if(appBar.isNull()){
|
||||
return nullptr;
|
||||
}
|
||||
QVariant var;
|
||||
QMetaObject::invokeMethod(appBar.value<QObject*>(), "maximizeButton",Q_RETURN_ARG(QVariant, var));
|
||||
if(var.isNull()){
|
||||
return nullptr;
|
||||
}
|
||||
return var.value<QObject*>();
|
||||
}
|
||||
|
||||
void FluFramelessHelper::setOriginalPos(QVariant pos){
|
||||
_originalPos.write(pos);
|
||||
}
|
||||
|
||||
bool FluFramelessHelper::resizeable(){
|
||||
return !(window->width() == window->maximumWidth() && window->width() == window->minimumWidth() && window->height() == window->maximumHeight() && window->height() == window->minimumHeight());
|
||||
}
|
||||
|
||||
bool FluFramelessHelper::_maximized(){
|
||||
return window->visibility() == QWindow::Maximized;
|
||||
}
|
||||
|
||||
bool FluFramelessHelper::_fullScreen(){
|
||||
return window->visibility() == QWindow::FullScreen;
|
||||
}
|
||||
|
@ -15,13 +15,15 @@ using QT_NATIVE_EVENT_RESULT_TYPE = long;
|
||||
using QT_ENTER_EVENT_TYPE = QEvent;
|
||||
#endif
|
||||
|
||||
class FluFramelessHelper;
|
||||
|
||||
class FramelessEventFilter : public QAbstractNativeEventFilter
|
||||
{
|
||||
public:
|
||||
FramelessEventFilter(QQuickWindow* window);
|
||||
FramelessEventFilter(FluFramelessHelper* helper);
|
||||
bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override;
|
||||
public:
|
||||
QQuickWindow* _window = nullptr;
|
||||
QPointer<FluFramelessHelper> _helper = nullptr;
|
||||
qint64 _current = 0;
|
||||
};
|
||||
|
||||
@ -34,17 +36,28 @@ public:
|
||||
~FluFramelessHelper();
|
||||
void classBegin() override;
|
||||
void componentComplete() override;
|
||||
bool hoverMaxBtn();
|
||||
bool resizeable();
|
||||
QObject* maximizeButton();
|
||||
void setOriginalPos(QVariant pos);
|
||||
Q_INVOKABLE void showSystemMenu();
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
private:
|
||||
void updateCursor(int edges);
|
||||
void _updateCursor(int edges);
|
||||
bool _maximized();
|
||||
bool _fullScreen();
|
||||
Q_SLOT void _onStayTopChange();
|
||||
Q_SLOT void _onScreenChanged();
|
||||
public:
|
||||
QPointer<QQuickWindow> window = nullptr;
|
||||
private:
|
||||
QPointer<QQuickWindow> _window = nullptr;
|
||||
FramelessEventFilter* _nativeEvent = nullptr;
|
||||
QQmlProperty _stayTop;
|
||||
QQmlProperty _screen;
|
||||
QQmlProperty _originalPos;
|
||||
QQmlProperty _fixSize;
|
||||
QQmlProperty _accentColor;
|
||||
};
|
||||
|
||||
#endif // FLUFRAMELESSHELPER_H
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <QTextDocument>
|
||||
#include <QQuickWindow>
|
||||
#include <QDateTime>
|
||||
#include <QSettings>
|
||||
|
||||
FluTools::FluTools(QObject *parent):QObject{parent}{
|
||||
|
||||
@ -179,3 +180,63 @@ qint64 FluTools::currentTimestamp(){
|
||||
QIcon FluTools::windowIcon(){
|
||||
return QGuiApplication::windowIcon();
|
||||
}
|
||||
|
||||
int FluTools::cursorScreenIndex(){
|
||||
int screenIndex = 0;
|
||||
int screenCount = qApp->screens().count();
|
||||
if (screenCount > 1) {
|
||||
QPoint pos = QCursor::pos();
|
||||
for (int i = 0; i < screenCount; ++i) {
|
||||
if (qApp->screens().at(i)->geometry().contains(pos)) {
|
||||
screenIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return screenIndex;
|
||||
}
|
||||
|
||||
int FluTools::windowBuildNumber(){
|
||||
#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();
|
||||
return buildNumber;
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool FluTools::isWindows11OrGreater(){
|
||||
static QVariant var;
|
||||
if(var.isNull()){
|
||||
#if defined(Q_OS_WIN)
|
||||
auto buildNumber = windowBuildNumber();
|
||||
if(buildNumber>=22000){
|
||||
var = QVariant::fromValue(true);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
var = QVariant::fromValue(false);
|
||||
return false;
|
||||
}else{
|
||||
return var.toBool();
|
||||
}
|
||||
}
|
||||
|
||||
bool FluTools::isWindows10OrGreater(){
|
||||
static QVariant var;
|
||||
if(var.isNull()){
|
||||
#if defined(Q_OS_WIN)
|
||||
auto buildNumber = windowBuildNumber();
|
||||
if(buildNumber>=10240){
|
||||
var = QVariant::fromValue(true);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
var = QVariant::fromValue(false);
|
||||
return false;
|
||||
}else{
|
||||
return var.toBool();
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,10 @@ public:
|
||||
Q_INVOKABLE qint64 currentTimestamp();
|
||||
Q_INVOKABLE QPoint cursorPos();
|
||||
Q_INVOKABLE QIcon windowIcon();
|
||||
Q_INVOKABLE int cursorScreenIndex();
|
||||
Q_INVOKABLE int windowBuildNumber();
|
||||
Q_INVOKABLE bool isWindows11OrGreater();
|
||||
Q_INVOKABLE bool isWindows10OrGreater();
|
||||
};
|
||||
|
||||
#endif // FLUTOOLS_H
|
||||
|
@ -116,7 +116,6 @@ void FluentUI::registerTypes(const char *uri){
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluSpinBox.qml"),uri,major,minor,"FluSpinBox");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluStatusView.qml"),uri,major,minor,"FluStatusView");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTabView.qml"),uri,major,minor,"FluTabView");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTableModelColumn.qml"),uri,major,minor,"FluTableModelColumn");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTableView.qml"),uri,major,minor,"FluTableView");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluText.qml"),uri,major,minor,"FluText");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluTextBox.qml"),uri,major,minor,"FluTextBox");
|
||||
|
@ -64,6 +64,11 @@ Rectangle{
|
||||
FluTheme.darkMode = FluThemeType.Dark
|
||||
}
|
||||
}
|
||||
property var systemMenuListener: function(){
|
||||
if(d.win instanceof FluWindow){
|
||||
d.win.showSystemMenu()
|
||||
}
|
||||
}
|
||||
id:control
|
||||
color: Qt.rgba(0,0,0,0)
|
||||
height: visible ? 30 : 0
|
||||
@ -71,6 +76,7 @@ Rectangle{
|
||||
z: 65535
|
||||
Item{
|
||||
id:d
|
||||
property bool hoverMaxBtn: false
|
||||
property var win: Window.window
|
||||
property bool stayTop: {
|
||||
if(d.win instanceof FluWindow){
|
||||
@ -83,14 +89,23 @@ Rectangle{
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onPositionChanged: {
|
||||
onPositionChanged:
|
||||
(mouse)=>{
|
||||
d.win.startSystemMove()
|
||||
}
|
||||
onDoubleClicked: {
|
||||
if(d.resizable){
|
||||
onDoubleClicked:
|
||||
(mouse)=>{
|
||||
if(d.resizable && Qt.LeftButton){
|
||||
btn_maximize.clicked()
|
||||
}
|
||||
}
|
||||
acceptedButtons: Qt.LeftButton|Qt.RightButton
|
||||
onClicked:
|
||||
(mouse)=>{
|
||||
if (mouse.button === Qt.RightButton){
|
||||
control.systemMenuListener()
|
||||
}
|
||||
}
|
||||
}
|
||||
Row{
|
||||
anchors{
|
||||
@ -218,6 +233,9 @@ Rectangle{
|
||||
if(pressed){
|
||||
return maximizePressColor
|
||||
}
|
||||
if(FluTools.isWindows11OrGreater()){
|
||||
return d.hoverMaxBtn ? maximizeHoverColor : maximizeNormalColor
|
||||
}
|
||||
return hovered ? maximizeHoverColor : maximizeNormalColor
|
||||
}
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
@ -263,4 +281,17 @@ Rectangle{
|
||||
function darkButton(){
|
||||
return btn_dark
|
||||
}
|
||||
function maximizeButtonHover(){
|
||||
var hover = false;
|
||||
var pos = btn_maximize.mapToGlobal(0,0)
|
||||
if(btn_maximize.visible){
|
||||
var rect = Qt.rect(pos.x,pos.y,btn_maximize.width,btn_maximize.height)
|
||||
pos = FluTools.cursorPos()
|
||||
if(pos.x>rect.x && pos.x<(rect.x+rect.width) && pos.y>rect.y && pos.y<(rect.y+rect.height)){
|
||||
hover = true;
|
||||
}
|
||||
}
|
||||
d.hoverMaxBtn = hover
|
||||
return hover;
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ TextArea{
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.IBeamCursor
|
||||
acceptedButtons: Qt.RightButton
|
||||
visible: !readOnly
|
||||
onClicked: control.echoMode !== TextInput.Password && menu.popup()
|
||||
}
|
||||
FluTextBoxMenu{
|
||||
|
@ -8,21 +8,17 @@ QtObject {
|
||||
property var _ext
|
||||
property var _parent
|
||||
property string title
|
||||
property int order : 0
|
||||
property var url
|
||||
property bool disabled: false
|
||||
property int icon
|
||||
property bool iconVisible: true
|
||||
property Component infoBadge
|
||||
property bool recentlyAdded: false
|
||||
property bool recentlyUpdated: false
|
||||
property string desc
|
||||
property var image
|
||||
property int count: 0
|
||||
property var onTapListener
|
||||
property Component iconDelegate
|
||||
property Component menuDelegate
|
||||
property Component editDelegate
|
||||
property var extra
|
||||
property bool showEdit
|
||||
signal tap
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
import Qt.labs.qmlmodels 1.0
|
||||
|
||||
TableModelColumn{
|
||||
|
||||
}
|
@ -13,12 +13,11 @@ Rectangle {
|
||||
color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
|
||||
onColumnSourceChanged: {
|
||||
if(columnSource.length!==0){
|
||||
var com_column = Qt.createComponent("FluTableModelColumn.qml")
|
||||
if (com_column.status === Component.Ready) {
|
||||
var columns= []
|
||||
var header_rows = {}
|
||||
columnSource.forEach(function(item){
|
||||
var column = com_column.createObject(table_model,{display:item.dataIndex});
|
||||
var column = Qt.createQmlObject('import Qt.labs.qmlmodels 1.0;TableModelColumn{}',table_model);
|
||||
column.display = item.dataIndex
|
||||
columns.push(column)
|
||||
header_rows[item.dataIndex] = item.title
|
||||
})
|
||||
@ -27,7 +26,6 @@ Rectangle {
|
||||
d.header_rows = [header_rows]
|
||||
}
|
||||
}
|
||||
}
|
||||
QtObject{
|
||||
id:d
|
||||
property var currentRow
|
||||
|
@ -62,6 +62,7 @@ TextField{
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.IBeamCursor
|
||||
acceptedButtons: Qt.RightButton
|
||||
visible: !readOnly
|
||||
onClicked: control.echoMode !== TextInput.Password && menu.popup()
|
||||
}
|
||||
RowLayout{
|
||||
|
@ -40,7 +40,12 @@ Window {
|
||||
property bool showStayTop: true
|
||||
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 color resizeBorderColor: {
|
||||
if(window.active){
|
||||
return _accentColor
|
||||
}
|
||||
return FluTheme.dark ? "#3D3D3E" : "#A7A7A7"
|
||||
}
|
||||
property int resizeBorderWidth: 1
|
||||
property var closeListener: function(event){
|
||||
if(closeDestory){
|
||||
@ -50,22 +55,22 @@ Window {
|
||||
event.accepted = false
|
||||
}
|
||||
}
|
||||
signal showSystemMenu
|
||||
signal initArgument(var argument)
|
||||
signal firstVisible()
|
||||
property point _offsetXY : Qt.point(0,0)
|
||||
property var _originalPos
|
||||
property color _accentColor : FluTheme.dark ? "#333333" : "#6E6E6E"
|
||||
id:window
|
||||
maximumWidth: fixSize ? width : 16777215
|
||||
maximumHeight: fixSize ? height : 16777215
|
||||
minimumWidth: fixSize ? width : 0
|
||||
minimumHeight: fixSize ? height : 0
|
||||
color:"transparent"
|
||||
Component.onCompleted: {
|
||||
moveWindowToDesktopCenter()
|
||||
useSystemAppBar = FluApp.useSystemAppBar
|
||||
if(!useSystemAppBar){
|
||||
loader_frameless.sourceComponent = com_frameless
|
||||
loader_frameless_helper.sourceComponent = com_frameless
|
||||
}
|
||||
lifecycle.onCompleted(window)
|
||||
initArgument(argument)
|
||||
moveWindowToDesktopCenter()
|
||||
if(window.autoMaximize){
|
||||
window.showMaximized()
|
||||
}else{
|
||||
@ -75,6 +80,24 @@ Window {
|
||||
Component.onDestruction: {
|
||||
lifecycle.onDestruction()
|
||||
}
|
||||
on_OriginalPosChanged: {
|
||||
if(_originalPos){
|
||||
var dx = (_originalPos.x - screen.virtualX)/screen.devicePixelRatio
|
||||
var dy = _originalPos.y - screen.virtualY/screen.devicePixelRatio
|
||||
if(dx<0 && dy<0){
|
||||
_offsetXY = Qt.point(Math.abs(dx),Math.abs(dy))
|
||||
}else{
|
||||
_offsetXY = Qt.point(0,0)
|
||||
}
|
||||
}else{
|
||||
_offsetXY = Qt.point(0,0)
|
||||
}
|
||||
}
|
||||
onShowSystemMenu: {
|
||||
if(loader_frameless_helper.item){
|
||||
loader_frameless_helper.item.showSystemMenu()
|
||||
}
|
||||
}
|
||||
onVisibleChanged: {
|
||||
if(visible && d.isFirstVisible){
|
||||
window.firstVisible()
|
||||
@ -169,34 +192,13 @@ Window {
|
||||
}
|
||||
}
|
||||
FluLoader{
|
||||
id:loader_frameless
|
||||
id:loader_frameless_helper
|
||||
}
|
||||
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
|
||||
topMargin: _offsetXY.y
|
||||
}
|
||||
onWidthChanged: {
|
||||
window.appBar.width = width
|
||||
@ -249,7 +251,27 @@ Window {
|
||||
border.width: window.resizeBorderWidth
|
||||
border.color: window.resizeBorderColor
|
||||
visible: {
|
||||
if(window.useSystemAppBar){
|
||||
if(window.useSystemAppBar || FluTools.isWindows10OrGreater()){
|
||||
return false
|
||||
}
|
||||
if(FluTools.isMacos()){
|
||||
if(window.visibility == Window.FullScreen){
|
||||
return false
|
||||
}
|
||||
}else{
|
||||
if(window.visibility == Window.Maximized || window.visibility == Window.FullScreen){
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
height: 1
|
||||
width: parent.width
|
||||
color: window.resizeBorderColor
|
||||
visible: {
|
||||
if(window.useSystemAppBar || !FluTools.isWin()){
|
||||
return false
|
||||
}
|
||||
if(window.visibility == Window.Maximized || window.visibility == Window.FullScreen){
|
||||
@ -286,7 +308,14 @@ Window {
|
||||
return lifecycle.createRegister(window,path)
|
||||
}
|
||||
function moveWindowToDesktopCenter(){
|
||||
screen = Qt.application.screens[FluTools.cursorScreenIndex()]
|
||||
window.setGeometry((Screen.width-window.width)/2+Screen.virtualX,(Screen.height-window.height)/2+Screen.virtualY,window.width,window.height)
|
||||
if(fixSize){
|
||||
maximumWidth = width
|
||||
maximumHeight = height
|
||||
minimumWidth = width
|
||||
minimumHeight = height
|
||||
}
|
||||
}
|
||||
function onResult(data){
|
||||
if(_pageRegister){
|
||||
|
@ -75,7 +75,6 @@ FluSlider 1.0 Controls/FluSlider.qml
|
||||
FluSpinBox 1.0 Controls/FluSpinBox.qml
|
||||
FluStatusView 1.0 Controls/FluStatusView.qml
|
||||
FluTabView 1.0 Controls/FluTabView.qml
|
||||
FluTableModelColumn 1.0 Controls/FluTableModelColumn.qml
|
||||
FluTableView 1.0 Controls/FluTableView.qml
|
||||
FluText 1.0 Controls/FluText.qml
|
||||
FluTextBox 1.0 Controls/FluTextBox.qml
|
||||
|
@ -71,7 +71,6 @@
|
||||
<file>FluentUI/Controls/FluSpinBox.qml</file>
|
||||
<file>FluentUI/Controls/FluStaggeredView.qml</file>
|
||||
<file>FluentUI/Controls/FluStatusView.qml</file>
|
||||
<file>FluentUI/Controls/FluTableModelColumn.qml</file>
|
||||
<file>FluentUI/Controls/FluTableView.qml</file>
|
||||
<file>FluentUI/Controls/FluTabView.qml</file>
|
||||
<file>FluentUI/Controls/FluText.qml</file>
|
||||
|
@ -64,6 +64,11 @@ Rectangle{
|
||||
FluTheme.darkMode = FluThemeType.Dark
|
||||
}
|
||||
}
|
||||
property var systemMenuListener: function(){
|
||||
if(d.win instanceof FluWindow){
|
||||
d.win.showSystemMenu()
|
||||
}
|
||||
}
|
||||
id:control
|
||||
color: Qt.rgba(0,0,0,0)
|
||||
height: visible ? 30 : 0
|
||||
@ -71,6 +76,7 @@ Rectangle{
|
||||
z: 65535
|
||||
Item{
|
||||
id:d
|
||||
property bool hoverMaxBtn: false
|
||||
property var win: Window.window
|
||||
property bool stayTop: {
|
||||
if(d.win instanceof FluWindow){
|
||||
@ -83,14 +89,23 @@ Rectangle{
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onPositionChanged: {
|
||||
onPositionChanged:
|
||||
(mouse)=>{
|
||||
d.win.startSystemMove()
|
||||
}
|
||||
onDoubleClicked: {
|
||||
if(d.resizable){
|
||||
onDoubleClicked:
|
||||
(mouse)=>{
|
||||
if(d.resizable && Qt.LeftButton){
|
||||
btn_maximize.clicked()
|
||||
}
|
||||
}
|
||||
acceptedButtons: Qt.LeftButton|Qt.RightButton
|
||||
onClicked:
|
||||
(mouse)=>{
|
||||
if (mouse.button === Qt.RightButton){
|
||||
control.systemMenuListener()
|
||||
}
|
||||
}
|
||||
}
|
||||
Row{
|
||||
anchors{
|
||||
@ -218,6 +233,9 @@ Rectangle{
|
||||
if(pressed){
|
||||
return maximizePressColor
|
||||
}
|
||||
if(FluTools.isWindows11OrGreater()){
|
||||
return d.hoverMaxBtn ? maximizeHoverColor : maximizeNormalColor
|
||||
}
|
||||
return hovered ? maximizeHoverColor : maximizeNormalColor
|
||||
}
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
@ -263,4 +281,17 @@ Rectangle{
|
||||
function darkButton(){
|
||||
return btn_dark
|
||||
}
|
||||
function maximizeButtonHover(){
|
||||
var hover = false;
|
||||
var pos = btn_maximize.mapToGlobal(0,0)
|
||||
if(btn_maximize.visible){
|
||||
var rect = Qt.rect(pos.x,pos.y,btn_maximize.width,btn_maximize.height)
|
||||
pos = FluTools.cursorPos()
|
||||
if(pos.x>rect.x && pos.x<(rect.x+rect.width) && pos.y>rect.y && pos.y<(rect.y+rect.height)){
|
||||
hover = true;
|
||||
}
|
||||
}
|
||||
d.hoverMaxBtn = hover
|
||||
return hover;
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ TextArea{
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.IBeamCursor
|
||||
acceptedButtons: Qt.RightButton
|
||||
visible: !readOnly
|
||||
onClicked: control.echoMode !== TextInput.Password && menu.popup()
|
||||
}
|
||||
FluTextBoxMenu{
|
||||
|
@ -8,21 +8,17 @@ QtObject {
|
||||
property var _ext
|
||||
property var _parent
|
||||
property string title
|
||||
property int order : 0
|
||||
property var url
|
||||
property bool disabled: false
|
||||
property int icon
|
||||
property bool iconVisible: true
|
||||
property Component infoBadge
|
||||
property bool recentlyAdded: false
|
||||
property bool recentlyUpdated: false
|
||||
property string desc
|
||||
property var image
|
||||
property int count: 0
|
||||
property var onTapListener
|
||||
property Component iconDelegate
|
||||
property Component menuDelegate
|
||||
property Component editDelegate
|
||||
property var extra
|
||||
property bool showEdit
|
||||
signal tap
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
import Qt.labs.qmlmodels
|
||||
|
||||
TableModelColumn{
|
||||
|
||||
}
|
@ -14,12 +14,11 @@ Rectangle {
|
||||
color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
|
||||
onColumnSourceChanged: {
|
||||
if(columnSource.length!==0){
|
||||
var com_column = Qt.createComponent("FluTableModelColumn.qml")
|
||||
if (com_column.status === Component.Ready) {
|
||||
var columns= []
|
||||
var header_rows = {}
|
||||
columnSource.forEach(function(item){
|
||||
var column = com_column.createObject(table_model,{display:item.dataIndex});
|
||||
var column = Qt.createQmlObject('import Qt.labs.qmlmodels;TableModelColumn{}',table_model);
|
||||
column.display = item.dataIndex
|
||||
columns.push(column)
|
||||
header_rows[item.dataIndex] = item.title
|
||||
})
|
||||
@ -28,7 +27,6 @@ Rectangle {
|
||||
d.header_rows = [header_rows]
|
||||
}
|
||||
}
|
||||
}
|
||||
QtObject{
|
||||
id:d
|
||||
property var currentRow
|
||||
|
@ -63,6 +63,7 @@ TextField{
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.IBeamCursor
|
||||
acceptedButtons: Qt.RightButton
|
||||
visible: !readOnly
|
||||
onClicked: control.echoMode !== TextInput.Password && menu.popup()
|
||||
}
|
||||
RowLayout{
|
||||
|
@ -39,7 +39,12 @@ Window {
|
||||
property bool showStayTop: true
|
||||
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 color resizeBorderColor: {
|
||||
if(window.active){
|
||||
return _accentColor
|
||||
}
|
||||
return FluTheme.dark ? "#3D3D3E" : "#A7A7A7"
|
||||
}
|
||||
property int resizeBorderWidth: 1
|
||||
property var closeListener: function(event){
|
||||
if(closeDestory){
|
||||
@ -49,22 +54,22 @@ Window {
|
||||
event.accepted = false
|
||||
}
|
||||
}
|
||||
signal showSystemMenu
|
||||
signal initArgument(var argument)
|
||||
signal firstVisible()
|
||||
property point _offsetXY : Qt.point(0,0)
|
||||
property var _originalPos
|
||||
property color _accentColor : FluTheme.dark ? "#333333" : "#6E6E6E"
|
||||
id:window
|
||||
maximumWidth: fixSize ? width : 16777215
|
||||
maximumHeight: fixSize ? height : 16777215
|
||||
minimumWidth: fixSize ? width : 0
|
||||
minimumHeight: fixSize ? height : 0
|
||||
color:"transparent"
|
||||
Component.onCompleted: {
|
||||
moveWindowToDesktopCenter()
|
||||
useSystemAppBar = FluApp.useSystemAppBar
|
||||
if(!useSystemAppBar){
|
||||
loader_frameless.sourceComponent = com_frameless
|
||||
loader_frameless_helper.sourceComponent = com_frameless
|
||||
}
|
||||
lifecycle.onCompleted(window)
|
||||
initArgument(argument)
|
||||
moveWindowToDesktopCenter()
|
||||
if(window.autoMaximize){
|
||||
window.showMaximized()
|
||||
}else{
|
||||
@ -74,6 +79,24 @@ Window {
|
||||
Component.onDestruction: {
|
||||
lifecycle.onDestruction()
|
||||
}
|
||||
on_OriginalPosChanged: {
|
||||
if(_originalPos){
|
||||
var dx = (_originalPos.x - screen.virtualX)/screen.devicePixelRatio
|
||||
var dy = _originalPos.y - screen.virtualY/screen.devicePixelRatio
|
||||
if(dx<0 && dy<0){
|
||||
_offsetXY = Qt.point(Math.abs(dx),Math.abs(dy))
|
||||
}else{
|
||||
_offsetXY = Qt.point(0,0)
|
||||
}
|
||||
}else{
|
||||
_offsetXY = Qt.point(0,0)
|
||||
}
|
||||
}
|
||||
onShowSystemMenu: {
|
||||
if(loader_frameless_helper.item){
|
||||
loader_frameless_helper.item.showSystemMenu()
|
||||
}
|
||||
}
|
||||
onVisibleChanged: {
|
||||
if(visible && d.isFirstVisible){
|
||||
window.firstVisible()
|
||||
@ -168,34 +191,13 @@ Window {
|
||||
}
|
||||
}
|
||||
FluLoader{
|
||||
id:loader_frameless
|
||||
id:loader_frameless_helper
|
||||
}
|
||||
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
|
||||
topMargin: _offsetXY.y
|
||||
}
|
||||
onWidthChanged: {
|
||||
window.appBar.width = width
|
||||
@ -248,7 +250,27 @@ Window {
|
||||
border.width: window.resizeBorderWidth
|
||||
border.color: window.resizeBorderColor
|
||||
visible: {
|
||||
if(window.useSystemAppBar){
|
||||
if(window.useSystemAppBar || FluTools.isWindows10OrGreater()){
|
||||
return false
|
||||
}
|
||||
if(FluTools.isMacos()){
|
||||
if(window.visibility == Window.FullScreen){
|
||||
return false
|
||||
}
|
||||
}else{
|
||||
if(window.visibility == Window.Maximized || window.visibility == Window.FullScreen){
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
height: 1
|
||||
width: parent.width
|
||||
color: window.resizeBorderColor
|
||||
visible: {
|
||||
if(window.useSystemAppBar || !FluTools.isWin()){
|
||||
return false
|
||||
}
|
||||
if(window.visibility == Window.Maximized || window.visibility == Window.FullScreen){
|
||||
@ -285,7 +307,14 @@ Window {
|
||||
return lifecycle.createRegister(window,path)
|
||||
}
|
||||
function moveWindowToDesktopCenter(){
|
||||
screen = Qt.application.screens[FluTools.cursorScreenIndex()]
|
||||
window.setGeometry((Screen.width-window.width)/2+Screen.virtualX,(Screen.height-window.height)/2+Screen.virtualY,window.width,window.height)
|
||||
if(fixSize){
|
||||
maximumWidth = width
|
||||
maximumHeight = height
|
||||
minimumWidth = width
|
||||
minimumHeight = height
|
||||
}
|
||||
}
|
||||
function onResult(data){
|
||||
if(_pageRegister){
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "FluRegister.h"
|
||||
|
||||
WindowLifecycle::WindowLifecycle(QObject *parent):QObject{parent}{
|
||||
|
||||
}
|
||||
|
||||
void WindowLifecycle::onCompleted(QQuickWindow* window){
|
||||
@ -12,7 +13,10 @@ void WindowLifecycle::onCompleted(QQuickWindow* window){
|
||||
}
|
||||
|
||||
void WindowLifecycle::onDestoryOnClose(){
|
||||
if(_window){
|
||||
FluApp::getInstance()->removeWindow(this->_window);
|
||||
_window = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowLifecycle::onDestruction(){
|
||||
|
@ -23,7 +23,7 @@ public:
|
||||
Q_INVOKABLE void onDestoryOnClose();
|
||||
Q_INVOKABLE QVariant createRegister(QQuickWindow* window,const QString& path);
|
||||
private:
|
||||
QQuickWindow* _window;
|
||||
QQuickWindow* _window = nullptr;
|
||||
};
|
||||
|
||||
#endif // WINDOWLIFECYCLE_H
|
||||
|
@ -44,4 +44,10 @@ private: \
|
||||
return Singleton<Class>::getInstance(); \
|
||||
}
|
||||
|
||||
#define HIDE_CONSTRUCTOR(Class) \
|
||||
private: \
|
||||
Class() = default; \
|
||||
Class(const Class& other) = delete; \
|
||||
Class& operator=(const Class& other) = delete;
|
||||
|
||||
#endif // SINGLETON_H
|
||||
|
Reference in New Issue
Block a user