This commit is contained in:
朱子楚\zhuzi 2024-04-12 16:26:32 +08:00
parent 44acdbcf7f
commit 0ab315e258
19 changed files with 264 additions and 24 deletions

View File

@ -2190,6 +2190,11 @@ Some contents...</source>
<source>Open Animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Theme.qml" line="123"/>
<source>Open Blur Window</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>T_TimePicker</name>

View File

@ -2280,6 +2280,11 @@ Some contents...</source>
<source>Open Animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qml/page/T_Theme.qml" line="123"/>
<source>Open Blur Window</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>T_TimePicker</name>

View File

@ -13,7 +13,7 @@ FluScrollablePage{
FluFrame{
Layout.fillWidth: true
Layout.preferredHeight: 340
Layout.preferredHeight: 400
padding: 10
ColumnLayout{
@ -119,6 +119,17 @@ FluScrollablePage{
FluTheme.animationEnabled = !FluTheme.animationEnabled
}
}
FluText{
text: qsTr("Open Blur Window")
Layout.topMargin: 20
}
FluToggleSwitch{
Layout.topMargin: 5
checked: FluTheme.blurBehindWindowEnabled
onClicked: {
FluTheme.blurBehindWindowEnabled = !FluTheme.blurBehindWindowEnabled
}
}
}
}
CodeExpander{

View File

@ -2,9 +2,11 @@
#include <QGuiApplication>
#include <QPalette>
#include <QImage>
#include "Def.h"
#include "FluentIconDef.h"
#include "FluColors.h"
#include "FluTools.h"
bool systemDark() {
QPalette palette = QGuiApplication::palette();
@ -18,13 +20,20 @@ FluTheme::FluTheme(QObject *parent) : QObject{parent} {
_nativeText = false;
_animationEnabled = true;
_systemDark = systemDark();
_desktopImagePath = "";
_blurBehindWindowEnabled = false;
QGuiApplication::instance()->installEventFilter(this);
refreshColors();
updateDesktopImage();
connect(this, &FluTheme::darkModeChanged, this, [=] {
Q_EMIT darkChanged();
});
connect(this, &FluTheme::darkChanged, this, [=] { refreshColors(); });
connect(this, &FluTheme::accentColorChanged, this, [=] { refreshColors(); });
refreshColors();
connect(&_watcher, &QFileSystemWatcher::fileChanged, this, [=](const QString &path){
Q_EMIT desktopImagePathChanged();
});
startTimer(500);
}
void FluTheme::refreshColors() {
@ -38,6 +47,8 @@ void FluTheme::refreshColors() {
fontSecondaryColor(isDark ? QColor(222, 222, 222, 255) : QColor(102, 102, 102, 255));
fontTertiaryColor(isDark ? QColor(200, 200, 200, 255) : QColor(153, 153, 153, 255));
itemNormalColor(isDark ? QColor(255, 255, 255, 0) : QColor(0, 0, 0, 0));
frameColor(isDark ? QColor(255, 255, 255, qRound(255 * 0.12)) : QColor(0, 0, 0, qRound(255 * 0.09)));
frameActiveColor(isDark ? QColor(32, 32, 32, qRound(255 * 0.8)) : QColor(255, 255, 255, qRound(255 * 0.6)));
itemHoverColor(isDark ? QColor(255, 255, 255, qRound(255 * 0.06)) : QColor(0, 0, 0, qRound(255 * 0.03)));
itemPressColor(isDark ? QColor(255, 255, 255, qRound(255 * 0.09)) : QColor(0, 0, 0, qRound(255 * 0.06)));
itemCheckColor(isDark ? QColor(255, 255, 255, qRound(255 * 0.12)) : QColor(0, 0, 0, qRound(255 * 0.09)));
@ -78,3 +89,19 @@ bool FluTheme::dark() const {
return false;
}
}
void FluTheme::updateDesktopImage(){
auto path = FluTools::getInstance()->getWallpaperFilePath();
if(_desktopImagePath != path){
if(!_desktopImagePath.isEmpty()){
_watcher.removePath(_desktopImagePath);
}
desktopImagePath(path);
_watcher.addPath(path);
}
}
void FluTheme::timerEvent(QTimerEvent *event)
{
updateDesktopImage();
}

View File

@ -6,6 +6,8 @@
#include <QJsonArray>
#include <QJsonObject>
#include <QColor>
#include <QTimer>
#include <QFileSystemWatcher>
#include "FluAccentColor.h"
#include "stdafx.h"
#include "singleton.h"
@ -26,12 +28,16 @@ Q_PROPERTY_AUTO(QColor, fontPrimaryColor);
Q_PROPERTY_AUTO(QColor, fontSecondaryColor);
Q_PROPERTY_AUTO(QColor, fontTertiaryColor);
Q_PROPERTY_AUTO(QColor, itemNormalColor);
Q_PROPERTY_AUTO(QColor, frameColor);
Q_PROPERTY_AUTO(QColor, frameActiveColor);
Q_PROPERTY_AUTO(QColor, itemHoverColor);
Q_PROPERTY_AUTO(QColor, itemPressColor);
Q_PROPERTY_AUTO(QColor, itemCheckColor);
Q_PROPERTY_AUTO(QString, desktopImagePath);
Q_PROPERTY_AUTO(int, darkMode);
Q_PROPERTY_AUTO(bool, nativeText);
Q_PROPERTY_AUTO(bool, animationEnabled);
Q_PROPERTY_AUTO(bool, blurBehindWindowEnabled);
QML_NAMED_ELEMENT(FluTheme)
QML_SINGLETON
@ -42,6 +48,14 @@ private:
void refreshColors();
void updateBackgroundMainColor();
protected:
void timerEvent(QTimerEvent *event) override;
void updateDesktopImage();
public:
SINGLETON(FluTheme)
@ -55,6 +69,7 @@ SINGLETON(FluTheme)
private:
bool _systemDark;
QFileSystemWatcher _watcher;
};
#endif // FLUTHEME_H

View File

@ -16,6 +16,14 @@
#include <QDateTime>
#include <QSettings>
#ifdef Q_OS_WIN
#pragma comment (lib, "user32.lib")
#include <windows.h>
#include <windowsx.h>
#endif
FluTools::FluTools(QObject *parent) : QObject{parent} {
}
@ -244,3 +252,32 @@ bool FluTools::isWindows10OrGreater() {
QRect FluTools::desktopAvailableGeometry(QQuickWindow *window) {
return window->screen()->availableGeometry();
}
QString FluTools::getWallpaperFilePath() {
#if defined(Q_OS_WIN)
wchar_t path[MAX_PATH] = {};
if (::SystemParametersInfoW(SPI_GETDESKWALLPAPER, MAX_PATH, path, FALSE) == FALSE) {
return {};
}
return QString::fromWCharArray(path);
#endif
return {};
}
QColor FluTools::imageMainColor(const QImage& image, double bright) {
int step = 20;
int t = 0;
int r = 0, g = 0, b = 0;
for (int i = 0; i < image.width(); i += step) {
for (int j = 0; j < image.height(); j += step) {
if (image.valid(i, j)) {
t++;
QColor c = image.pixel(i, j);
r += c.red();
b += c.blue();
g += c.green();
}
}
}
return QColor(int(bright * r / t) > 255 ? 255 : int(bright * r / t), int(bright * g / t) > 255 ? 255 : int(bright * g / t), int(bright * b / t) > 255 ? 255 : int(bright * b / t));
}

View File

@ -92,4 +92,8 @@ SINGLETON(FluTools)
Q_INVOKABLE bool isWindows10OrGreater();
Q_INVOKABLE QRect desktopAvailableGeometry(QQuickWindow *window);
Q_INVOKABLE QString getWallpaperFilePath();
Q_INVOKABLE QColor imageMainColor(const QImage& image, double bright = 1);
};

View File

@ -8,7 +8,7 @@ Item {
property real tintOpacity: 0.65
property real luminosity: 0.01
property real noiseOpacity: 0.02
property alias target: effect_source.sourceItem
property var target
property int blurRadius: 32
property rect targetRect: Qt.rect(control.x, control.y, control.width,control.height)
ShaderEffectSource {
@ -16,6 +16,7 @@ Item {
anchors.fill: parent
visible: false
sourceRect: control.targetRect
sourceItem: control.target
}
FastBlur {
id: fast_blur
@ -33,7 +34,7 @@ Item {
}
Image {
anchors.fill: parent
source: "../Image/noise.png"
source: "qrc:/qt/qml/FluentUI/Image/noise.png"
fillMode: Image.Tile
opacity: control.noiseOpacity
}

View File

@ -76,10 +76,11 @@ FluButton {
}
contentItem: Item{
clip: true
FluFrame{
Rectangle{
id:container
width: 300
height: 360
color: FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1)
ColumnLayout {
anchors.fill: parent
spacing: 0

View File

@ -27,7 +27,12 @@ Item {
height: 45
radius: 4
border.color: FluTheme.dividerColor
color: FluTheme.dark ? Window.active ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
color: {
if(Window.active){
return FluTheme.frameActiveColor
}
return FluTheme.frameColor
}
MouseArea{
id:control_mouse
anchors.fill: parent
@ -84,12 +89,18 @@ Item {
height: contentHeight+container.anchors.topMargin
width: parent.width
z:-999
clip: true
Rectangle{
id:container
anchors.fill: parent
radius: 4
clip: true
color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
color: {
if(Window.active){
return FluTheme.frameActiveColor
}
return FluTheme.frameColor
}
border.color: FluTheme.dividerColor
anchors.topMargin: -contentHeight
states: [

View File

@ -19,6 +19,11 @@ T.Frame {
id:d
radius: 4
border.color: FluTheme.dividerColor
color: FluTheme.dark ? Window.active ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(251/255,251/255,253/255,1)
color: {
if(Window.active){
return FluTheme.frameActiveColor
}
return FluTheme.frameColor
}
}
}

View File

@ -8,8 +8,13 @@ import FluentUI 1.0
T.GroupBox {
id: control
property int borderWidth : 1
property color borderColor : FluTheme.dark ? Window.active ? Qt.rgba(55/255,55/255,55/255,1):Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1)
property color color: FluTheme.dark ? Window.active ? Qt.rgba(38/255,44/255,54/255,1) : Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
property color borderColor : FluTheme.dividerColor
property color color: {
if(Window.active){
return FluTheme.frameActiveColor
}
return FluTheme.frameColor
}
property int radius: 4
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
contentWidth + leftPadding + rightPadding,

View File

@ -109,9 +109,54 @@ Window {
}
Component{
id:com_background
Item{
Rectangle{
anchors.fill: parent
color: window.backgroundColor
}
Image{
id:img_back
visible: false
cache: false
Component.onCompleted: {
var geometry = FluTools.desktopAvailableGeometry(window)
width = geometry.width
height = geometry.height
sourceSize = Qt.size(width,height)
source = FluTools.getUrlByFilePath(FluTheme.desktopImagePath)
}
Connections{
target: FluTheme
function onDesktopImagePathChanged(){
timer_update_image.restart()
}
function onBlurBehindWindowEnabledChanged(){
if(FluTheme.blurBehindWindowEnabled){
img_back.source = FluTools.getUrlByFilePath(FluTheme.desktopImagePath)
}else{
img_back.source = ""
}
}
}
Timer{
id:timer_update_image
interval: 500
onTriggered: {
img_back.source = ""
img_back.source = FluTools.getUrlByFilePath(FluTheme.desktopImagePath)
}
}
}
FluAcrylic{
anchors.fill: parent
target: img_back
tintOpacity: FluTheme.dark ? 0.80 : 0.75
blurRadius: 64
visible: window.active && FluTheme.blurBehindWindowEnabled
tintColor: FluTheme.dark ? Qt.rgba(0, 0, 0, 1) : Qt.rgba(1, 1, 1, 1)
targetRect: Qt.rect(window.x,window.y,window.width,window.height)
}
}
}
Component{
id:com_app_bar

View File

@ -8,7 +8,7 @@ Item {
property real tintOpacity: 0.65
property real luminosity: 0.01
property real noiseOpacity: 0.02
property alias target: effect_source.sourceItem
property var target
property int blurRadius: 32
property rect targetRect: Qt.rect(control.x, control.y, control.width,control.height)
ShaderEffectSource {
@ -16,6 +16,7 @@ Item {
anchors.fill: parent
visible: false
sourceRect: control.targetRect
sourceItem: control.target
}
FastBlur {
id: fast_blur
@ -33,7 +34,7 @@ Item {
}
Image {
anchors.fill: parent
source: "../Image/noise.png"
source: "qrc:/qt/qml/FluentUI/Image/noise.png"
fillMode: Image.Tile
opacity: control.noiseOpacity
}

View File

@ -75,10 +75,11 @@ FluButton {
}
contentItem: Item{
clip: true
FluFrame{
Rectangle{
id:container
width: 300
height: 360
color: FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1)
ColumnLayout {
anchors.fill: parent
spacing: 0

View File

@ -27,7 +27,12 @@ Item {
height: 45
radius: 4
border.color: FluTheme.dividerColor
color: FluTheme.dark ? Window.active ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
color: {
if(Window.active){
return FluTheme.frameActiveColor
}
return FluTheme.frameColor
}
MouseArea{
id:control_mouse
anchors.fill: parent
@ -84,12 +89,18 @@ Item {
height: contentHeight+container.anchors.topMargin
width: parent.width
z:-999
clip: true
Rectangle{
id:container
anchors.fill: parent
radius: 4
clip: true
color: FluTheme.dark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
color: {
if(Window.active){
return FluTheme.frameActiveColor
}
return FluTheme.frameColor
}
border.color: FluTheme.dividerColor
anchors.topMargin: -contentHeight
states: [

View File

@ -17,6 +17,11 @@ T.Frame {
id:d
radius: 4
border.color: FluTheme.dividerColor
color: FluTheme.dark ? Window.active ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(251/255,251/255,253/255,1)
color: {
if(Window.active){
return FluTheme.frameActiveColor
}
return FluTheme.frameColor
}
}
}

View File

@ -8,8 +8,13 @@ import FluentUI
T.GroupBox {
id: control
property int borderWidth : 1
property color borderColor : FluTheme.dark ? Window.active ? Qt.rgba(55/255,55/255,55/255,1):Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1)
property color color: FluTheme.dark ? Window.active ? Qt.rgba(38/255,44/255,54/255,1) : Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(251/255,251/255,253/255,1)
property color borderColor : FluTheme.dividerColor
property color color: {
if(Window.active){
return FluTheme.frameActiveColor
}
return FluTheme.frameColor
}
property int radius: 4
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
contentWidth + leftPadding + rightPadding,

View File

@ -108,9 +108,54 @@ Window {
}
Component{
id:com_background
Item{
Rectangle{
anchors.fill: parent
color: window.backgroundColor
}
Image{
id:img_back
visible: false
cache: false
Component.onCompleted: {
var geometry = FluTools.desktopAvailableGeometry(window)
width = geometry.width
height = geometry.height
sourceSize = Qt.size(width,height)
source = FluTools.getUrlByFilePath(FluTheme.desktopImagePath)
}
Connections{
target: FluTheme
function onDesktopImagePathChanged(){
timer_update_image.restart()
}
function onBlurBehindWindowEnabledChanged(){
if(FluTheme.blurBehindWindowEnabled){
img_back.source = FluTools.getUrlByFilePath(FluTheme.desktopImagePath)
}else{
img_back.source = ""
}
}
}
Timer{
id:timer_update_image
interval: 500
onTriggered: {
img_back.source = ""
img_back.source = FluTools.getUrlByFilePath(FluTheme.desktopImagePath)
}
}
}
FluAcrylic{
anchors.fill: parent
target: img_back
tintOpacity: FluTheme.dark ? 0.80 : 0.75
blurRadius: 64
visible: window.active && FluTheme.blurBehindWindowEnabled
tintColor: FluTheme.dark ? Qt.rgba(0, 0, 0, 1) : Qt.rgba(1, 1, 1, 1)
targetRect: Qt.rect(window.x,window.y,window.width,window.height)
}
}
}
Component{
id:com_app_bar