Compare commits

..

32 Commits
1.2.3 ... 1.2.5

Author SHA1 Message Date
60c2ebee56 update 2023-04-19 10:14:35 +08:00
88fed82260 update 2023-04-19 09:41:08 +08:00
cb94db8a97 Merge pull request #53 from mentalfl0w/dev
Add automatic dark color mode switching function.
2023-04-16 02:30:08 +08:00
88008e16be update 2023-04-16 02:28:58 +08:00
f2db544be0 Add automatic dark color mode switching function. 2023-04-16 01:18:17 +08:00
6db8c4d4ac update 2023-04-15 21:20:00 +08:00
4ab78bbaba 修改registerForPageResult崩溃问题 2023-04-15 09:45:54 +08:00
11b2b04cb9 update 2023-04-14 17:43:19 +08:00
9f2e066a9f update 2023-04-14 17:36:33 +08:00
5b8312dcb9 update 2023-04-14 17:10:36 +08:00
b28f15c23b update 2023-04-14 17:07:54 +08:00
935f515a49 Merge branch 'main' of https://github.com/zhuzichu520/FluentUI 2023-04-14 15:18:32 +08:00
70585c007e 新增FluRatingControl组件 2023-04-14 15:18:08 +08:00
bdde046a4d Update README.md 2023-04-14 12:35:16 +08:00
ad420366f1 Update README.md 2023-04-14 12:34:51 +08:00
727a0220b4 update 2023-04-13 18:10:38 +08:00
ab0fcf5d9c FluWindowd新增launchMode枚举值,支持Standard、SingleTask、SingleInstance 2023-04-13 17:41:34 +08:00
f43bfec992 Merge pull request #43 from LiangLiang723/main
🔧 重构 FluWindow 后 CMakeLists 做对应修改
2023-04-13 16:36:12 +08:00
6bf38b5e5e 🔧 重构 FluWindow 后 CMakeLists 做对应修改 2023-04-13 15:01:04 +08:00
73ff2b45b9 update 2023-04-12 22:02:05 +08:00
7303e7d900 update 2023-04-12 13:42:45 +08:00
5ca1b715f3 update 2023-04-12 11:55:39 +08:00
cd984fddf5 update 2023-04-12 00:15:38 +08:00
2acb3c34bd update 2023-04-11 23:43:20 +08:00
1df3b4ba96 update 2023-04-11 23:39:20 +08:00
5ea3cb1054 Merge pull request #39 from zhuzichu520/dev1.2.4
update
2023-04-11 23:17:51 +08:00
5afd2ec518 update 2023-04-11 23:12:31 +08:00
59527fc954 Merge pull request #38 from zhuzichu520/dev1.2.4
update
2023-04-11 18:06:06 +08:00
c26fdfaee3 update 2023-04-11 18:05:07 +08:00
878dbd668b Merge pull request #36 from zhuzichu520/dev1.2.4
update
2023-04-11 16:31:35 +08:00
b10a0752fb update 2023-04-11 16:30:54 +08:00
51e73e7f8e fix bug 2023-04-11 16:30:07 +08:00
66 changed files with 1568 additions and 1193 deletions

View File

@ -2,7 +2,7 @@
## 简介
这是一个漂亮的Fluent组件库使用QML插件开发的
这是一个漂亮的Fluent组件库使用QML插件开发的。main分支是Qt6.4.3如果需要qt5的请切换至qt5分支
## 编译状态
| [Windows][win-link]| [Ubuntu][ubuntu-link]|[MacOS][macos-link]|

View File

@ -2,16 +2,12 @@
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Layouts
import QtMultimedia
import FluentUI
Window {
id:app
color: "#00000000"
//初始化一个MediaPlayer解决macos切换到T_MediaPalyer页面崩溃问题
MediaPlayer{}
Component.onCompleted: {
FluApp.init(app,properties)
FluApp.init(app)
FluTheme.frameless = ("windows" === Qt.platform.os)
FluTheme.dark = false
FluApp.routes = {
@ -20,9 +16,11 @@ Window {
"/login":"qrc:/page/LoginPage.qml",
"/chat":"qrc:/page/ChatPage.qml",
"/media":"qrc:/page/MediaPage.qml",
"/singleTaskWindow":"qrc:/page/SingleTaskWindow.qml",
"/standardWindow":"qrc:/page/StandardWindow.qml",
"/singleInstanceWindow":"qrc:/page/SingleInstanceWindow.qml"
}
FluApp.initialRoute = "/"
FluApp.run()
}
}

25
example/AppInfo.cpp Normal file
View File

@ -0,0 +1,25 @@
#include "AppInfo.h"
#include "lang/En.h"
#include "lang/Zh.h"
AppInfo::AppInfo(QObject *parent)
: QObject{parent}
{
version("1.2.5");
lang(new En());
}
void AppInfo::changeLang(const QString& locale){
if(_lang){
_lang->deleteLater();
}
if(locale=="Zh"){
lang(new Zh());
}else if(locale=="En"){
lang(new En());
}else {
lang(new En());
}
}

18
example/AppInfo.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef APPINFO_H
#define APPINFO_H
#include <QObject>
#include "lang/Lang.h"
#include "stdafx.h"
class AppInfo : public QObject
{
Q_OBJECT
Q_PROPERTY_AUTO(QString,version)
Q_PROPERTY_AUTO(Lang*,lang)
public:
explicit AppInfo(QObject *parent = nullptr);
Q_INVOKABLE void changeLang(const QString& locale);
};
#endif // APPINFO_H

View File

@ -25,11 +25,13 @@ find_package(Qt6 COMPONENTS Core Quick QuickControls2 Concurrent Network Multime
set(SOURCES
ChatController.cpp
AppInfo.cpp
main.cpp
)
set(HEADERS
ChatController.h
AppInfo.h
)
set(RESOURCES

View File

@ -24,6 +24,86 @@ FluScrollablePage{
}
}
FluArea{
Layout.fillWidth: true
height: 86
paddings: 10
Layout.topMargin: 20
Column{
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluText{
text:"<font color='red'>Standard</font>模式窗口,每次都会创建新窗口"
}
FluButton{
text:"点击创建窗口"
onClicked: {
FluApp.navigate("/standardWindow")
}
}
}
}
FluArea{
Layout.fillWidth: true
height: 86
paddings: 10
Layout.topMargin: 10
Column{
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluText{
text:"<font color='red'>SingleTask</font>模式窗口,如果窗口存在,这激活该窗口"
textFormat: Text.RichText
}
FluButton{
text:"点击创建窗口"
onClicked: {
FluApp.navigate("/singleTaskWindow")
}
}
}
}
FluArea{
Layout.fillWidth: true
height: 86
paddings: 10
Layout.topMargin: 10
Column{
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluText{
text:"<font color='red'>SingleInstance</font>模式窗口,如果窗口存在,则销毁窗口,然后新建窗口"
}
FluButton{
text:"点击创建窗口"
onClicked: {
FluApp.navigate("/singleInstanceWindow")
}
}
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluWindow{
//launchMode: FluWindow.Standard
//launchMode: FluWindow.SingleTask
launchMode: FluWindow.SingleInstance
}
'
}
FluArea{
Layout.fillWidth: true
height: 100

View File

@ -21,6 +21,7 @@ FluScrollablePage{
FluPivot{
anchors.fill: parent
currentIndex: 2
FluPivotItem{
title:"All"
contentItem:FluText{

View File

@ -0,0 +1,43 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Window
import QtQuick.Controls
import FluentUI
import "./component"
FluScrollablePage{
title:"RatingControl"
leftPadding:10
rightPadding:10
bottomPadding:20
spacing: 0
FluArea{
Layout.fillWidth: true
height: 100
paddings: 10
Layout.topMargin: 20
Column{
spacing: 10
anchors.verticalCenter: parent.verticalCenter
FluRatingControl{
}
FluRatingControl{
number:10
}
}
}
CodeExpander{
Layout.fillWidth: true
code:'FluRatingControl{
}'
}
}

View File

@ -23,12 +23,12 @@ FluScrollablePage{
ColumnLayout{
spacing: 10
anchors{
verticalCenter: parent.verticalCenter
top: parent.top
left: parent.left
}
FluText{
text:"NavigationView Display Mode"
text:lang.navigation_view_display_mode
fontStyle: FluText.BodyStrong
Layout.bottomMargin: 4
}
@ -47,4 +47,42 @@ FluScrollablePage{
}
}
FluArea{
Layout.fillWidth: true
Layout.topMargin: 20
height: 168
paddings: 10
ColumnLayout{
spacing: 10
anchors{
top: parent.top
left: parent.left
}
FluText{
text:lang.locale
fontStyle: FluText.BodyStrong
Layout.bottomMargin: 4
}
Flow{
spacing: 5
Repeater{
model: ["Zh","En"]
delegate: FluRadioButton{
selected : appInfo.lang.objectName === modelData
text:modelData
onClicked:{
console.debug(modelData)
appInfo.changeLang(modelData)
}
}
}
}
}
}
}

View File

@ -118,7 +118,8 @@ FluExpander{
"FluTableView",
"FluColors",
"FluTheme",
"FluStatusView"
"FluStatusView",
"FluRatingControl"
];
code = code.replace(/\n/g, "<br>");
code = code.replace(/ /g, "&nbsp;");

View File

@ -3,10 +3,19 @@ CONFIG += c++17
DEFINES += QT_DEPRECATED_WARNINGS QT_NO_WARNING_OUTPUT
HEADERS += \
ChatController.h
lang/En.h \
lang/Lang.h \
lang/Zh.h \
stdafx.h \
ChatController.h \
AppInfo.h
SOURCES += \
ChatController.cpp \
AppInfo.cpp \
lang/En.cpp \
lang/Lang.cpp \
lang/Zh.cpp \
main.cpp
RESOURCES += qml.qrc

View File

@ -10,14 +10,14 @@ FluObject{
FluPaneItemSeparator{}
FluPaneItem{
title:"About"
title:lang.about
icon:FluentIcons.Contact
tapFunc:function(){
FluApp.navigate("/about")
}
}
FluPaneItem{
title:"Settings"
title:lang.settings
icon:FluentIcons.Settings
onTap:{
navigationView.push("qrc:/T_Settings.qml")

View File

@ -8,15 +8,22 @@ FluObject{
property var navigationView
FluPaneItem{
title:"Home"
icon:FluentIcons.Home
title:lang.home
// icon:FluentIcons.Home
cusIcon: Image{
anchors.centerIn: parent
source: FluTheme.dark ? "qrc:/res/svg/home_dark.svg" : "qrc:/res/svg/home.svg"
sourceSize: Qt.size(30,30)
width: 18
height: 18
}
onTap:{
navigationView.push("qrc:/T_Home.qml")
}
}
FluPaneItemExpander{
title:"Basic input"
title:lang.basic_input
icon:FluentIcons.CheckboxComposite
FluPaneItem{
title:"Buttons"
@ -54,7 +61,7 @@ FluObject{
}
FluPaneItemExpander{
title:"Form"
title:lang.form
icon:FluentIcons.GridView
FluPaneItem{
title:"TextBox"
@ -89,7 +96,7 @@ FluObject{
}
FluPaneItemExpander{
title:"Surface"
title:lang.surface
icon:FluentIcons.SurfaceHub
FluPaneItem{
title:"InfoBar"
@ -106,6 +113,12 @@ FluObject{
navigationView.push("qrc:/T_Progress.qml")
}
}
FluPaneItem{
title:"RatingControl"
onTap:{
navigationView.push("qrc:/T_RatingControl.qml")
}
}
FluPaneItem{
title:"Badge"
onTap:{
@ -139,7 +152,7 @@ FluObject{
}
FluPaneItemExpander{
title:"Popus"
title:lang.popus
icon:FluentIcons.ButtonMenu
FluPaneItem{
title:"Dialog"
@ -162,7 +175,7 @@ FluObject{
}
FluPaneItemExpander{
title:"Navigation"
title:lang.navigation
icon:FluentIcons.AllApps
FluPaneItem{
title:"Pivot"
@ -219,7 +232,7 @@ FluObject{
}
FluPaneItemExpander{
title:"Theming"
title:lang.theming
icon:FluentIcons.Brightness
FluPaneItem{
title:"Theme"
@ -242,7 +255,7 @@ FluObject{
}
FluPaneItemExpander{
title:"Media"
title:lang.media
icon:FluentIcons.Media
FluPaneItem{
title:"MediaPlayer"
@ -301,20 +314,7 @@ FluObject{
}
function startPageByItem(data){
var items = navigationView.getItems();
for(var i=0;i<items.length;i++){
var item = items[i]
if(item.key === data.key){
if(navigationView.getCurrentIndex() === i){
return
}
navigationView.setCurrentIndex(i)
if(item.parent){
item.parent.isExpand = true
}
return
}
}
navigationView.startPageByItem(data)
}
}

View File

@ -1,10 +1,9 @@
pragma Singleton
import QtQuick
import QtQuick.Controls
import FluentUI
QtObject {
property int displayMode : FluNavigationView.Auto
}

21
example/lang/En.cpp Normal file
View File

@ -0,0 +1,21 @@
#include "En.h"
En::En(QObject *parent)
: Lang{parent}
{
setObjectName("En");
home("Home");
basic_input("Basic Input");
form("Form");
surface("Surfaces");
popus("Popus");
navigation("Navigation");
theming("Theming");
media("Media");
dark_mode("Dark Mode");
search("Search");
about("About");
settings("Settings");
locale("Locale");
navigation_view_display_mode("NavigationView Display Mode");
}

17
example/lang/En.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef EN_H
#define EN_H
#include <QObject>
#include "Lang.h"
class En : public Lang
{
Q_OBJECT
public:
explicit En(QObject *parent = nullptr);
signals:
};
#endif // EN_H

7
example/lang/Lang.cpp Normal file
View File

@ -0,0 +1,7 @@
#include "Lang.h"
Lang::Lang(QObject *parent)
: QObject{parent}
{
}

29
example/lang/Lang.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef LANG_H
#define LANG_H
#include <QObject>
#include "stdafx.h"
class Lang : public QObject
{
Q_OBJECT
Q_PROPERTY_AUTO(QString,home);
Q_PROPERTY_AUTO(QString,basic_input);
Q_PROPERTY_AUTO(QString,form);
Q_PROPERTY_AUTO(QString,surface);
Q_PROPERTY_AUTO(QString,popus);
Q_PROPERTY_AUTO(QString,navigation);
Q_PROPERTY_AUTO(QString,theming);
Q_PROPERTY_AUTO(QString,media);
Q_PROPERTY_AUTO(QString,dark_mode);
Q_PROPERTY_AUTO(QString,search);
Q_PROPERTY_AUTO(QString,about);
Q_PROPERTY_AUTO(QString,settings);
Q_PROPERTY_AUTO(QString,navigation_view_display_mode);
Q_PROPERTY_AUTO(QString,locale);
public:
explicit Lang(QObject *parent = nullptr);
};
#endif // LANG_H

21
example/lang/Zh.cpp Normal file
View File

@ -0,0 +1,21 @@
#include "Zh.h"
Zh::Zh(QObject *parent)
: Lang{parent}
{
setObjectName("Zh");
home("首页");
basic_input("基本输入");
form("表单");
surface("表面");
popus("弹窗");
navigation("导航");
theming("主题");
media("媒体");
dark_mode("夜间模式");
search("查找");
about("关于");
settings("设置");
locale("语言环境");
navigation_view_display_mode("导航视图显示模式");
}

17
example/lang/Zh.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef ZH_H
#define ZH_H
#include <QObject>
#include "Lang.h"
class Zh : public Lang
{
Q_OBJECT
public:
explicit Zh(QObject *parent = nullptr);
signals:
};
#endif // ZH_H

View File

@ -5,14 +5,10 @@
#include <QQuickWindow>
#include <QQuickStyle>
#include <QProcess>
#include "lang/Lang.h"
#include "AppInfo.h"
#include "ChatController.h"
QMap<QString, QVariant> properties(){
QMap<QString, QVariant> map;
// map["installHelper"] = QVariant::fromValue(QVariant::fromValue(InstallHelper::getInstance()));
return map;
}
int main(int argc, char *argv[])
{
QCoreApplication::setOrganizationName("ZhuZiChu");
@ -20,18 +16,17 @@ int main(int argc, char *argv[])
QCoreApplication::setApplicationName("FluentUI");
QQuickStyle::setStyle("Basic");
QGuiApplication app(argc, argv);
app.setQuitOnLastWindowClosed(false);
QQmlApplicationEngine engine;
qmlRegisterType<ChatController>("Controller",1,0,"ChatController");
QMapIterator<QString, QVariant> iterator(properties());
while (iterator.hasNext()) {
iterator.next();
QString key = iterator.key();
QVariant value = iterator.value();
engine.rootContext()->setContextProperty(key,value);
}
engine.rootContext()->setContextProperty("properties",properties());
AppInfo* appInfo = new AppInfo();
QQmlContext * context = engine.rootContext();
Lang* lang = appInfo->lang();
context->setContextProperty("lang",lang);
QObject::connect(appInfo,&AppInfo::langChanged,&app,[context,appInfo]{
context->setContextProperty("lang",appInfo->lang());
});
context->setContextProperty("appInfo",appInfo);
const QUrl url(QStringLiteral("qrc:/App.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {

View File

@ -5,12 +5,15 @@ import FluentUI
FluWindow {
width: 500
id:window
width: 600
height: 600
minimumWidth: 500
minimumWidth: 600
minimumHeight: 600
maximumWidth: 500
maximumWidth: 600
maximumHeight: 600
launchMode: FluWindow.SingleTask
title:"关于"
@ -36,7 +39,7 @@ FluWindow {
fontStyle: FluText.Title
}
FluText{
text:"v1.2.3"
text:"v%1".arg(appInfo.version)
fontStyle: FluText.Body
Layout.alignment: Qt.AlignBottom
}
@ -57,7 +60,6 @@ FluWindow {
RowLayout{
spacing: 14
Layout.topMargin: 20
Layout.leftMargin: 15
FluText{
text:"GitHub"
@ -71,13 +73,28 @@ FluWindow {
}
}
}
RowLayout{
spacing: 14
Layout.leftMargin: 15
FluText{
text:"B站"
}
FluTextButton{
text:"https://www.bilibili.com/video/BV1mg4y1M71w/"
Layout.alignment: Qt.AlignBottom
onClicked: {
Qt.openUrlExternally(text)
}
}
}
RowLayout{
spacing: 14
Layout.topMargin: 20
Layout.leftMargin: 15
FluText{
id:text_info
text:"如果该项目对你有作用就请点击上方链接给一个免费的star"
text:"如果该项目对你有作用就请点击上方链接给一个免费的star,或者一键三连,谢谢"
ColorAnimation {
id: animation
target: text_info
@ -91,5 +108,43 @@ FluWindow {
}
}
}
RowLayout{
spacing: 14
Layout.leftMargin: 15
FluText{
text:"捐赠:"
}
}
Item{
Layout.preferredWidth: parent.width
Layout.preferredHeight: 252
Row{
anchors.horizontalCenter: parent.horizontalCenter
spacing: 60
Image{
width: 164.55
height: 224.25
source: "qrc:/res/image/qrcode_wx.jpg"
}
Image{
width: 162
height: 252
source: "qrc:/res/image/qrcode_zfb.jpg"
}
}
}
RowLayout{
spacing: 14
Layout.leftMargin: 15
FluText{
id:text_desc
text:"个人开发,维护不易,你们的捐赠就是我继续更新的动力!\n有什么问题提Issues只要时间充足我就会解决的"
}
}
}
}

View File

@ -12,8 +12,6 @@ FluWindow {
minimumHeight: 400
maximumWidth: 400
maximumHeight: 400
modality:2
title:"登录"
onInitArgument:

View File

@ -2,14 +2,16 @@
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Layouts
import "qrc:///global/"
import Qt.labs.platform
import FluentUI
import "qrc:///global/"
FluWindow {
id:rootwindow
id:window
width: 1000
height: 640
title: "FluentUI"
closeDestory:false
minimumWidth: 520
minimumHeight: 460
@ -18,9 +20,33 @@ FluWindow {
z:9
showDark: true
width:parent.width
darkText: "Dark Mode"
darkText: lang.dark_mode
}
SystemTrayIcon {
visible: true
icon.source: "qrc:/res/image/favicon.ico"
tooltip: "FluentUI"
menu: Menu {
MenuItem {
text: "退出"
onTriggered: {
window.destoryWindow()
FluApp.closeApp()
}
}
}
onActivated:
(reason)=>{
if(reason === SystemTrayIcon.Trigger){
window.show()
window.raise()
window.requestActivate()
}
}
}
FluNavigationView{
id:nav_view
anchors.fill: parent
@ -35,7 +61,7 @@ FluWindow {
anchors.centerIn: parent
iconSource: FluentIcons.Search
items: ItemsOriginal.getSearchData()
placeholderText: "Search"
placeholderText: lang.search
onItemClicked:
(data)=>{
ItemsOriginal.startPageByItem(data)

View File

@ -0,0 +1,46 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
FluWindow {
id:window
width: 500
height: 600
minimumWidth: 500
minimumHeight: 600
maximumWidth: 500
maximumHeight: 600
launchMode: FluWindow.SingleInstance
title:"SingleInstance"
FluAppBar{
id:appbar
title:"SingleInstance"
width:parent.width
}
FluTextBox{
anchors{
top:parent.top
topMargin:60
horizontalCenter: parent.horizontalCenter
}
}
FluText{
wrapMode: Text.WrapAnywhere
anchors{
left: parent.left
right: parent.right
leftMargin: 20
rightMargin: 20
verticalCenter: parent.verticalCenter
}
text:"我是一个SingleInstance模式的窗口如果我存在我会销毁之前的窗口并创建一个新窗口"
}
}

View File

@ -0,0 +1,31 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
FluWindow {
id:window
width: 500
height: 600
minimumWidth: 500
minimumHeight: 600
maximumWidth: 500
maximumHeight: 600
launchMode: FluWindow.SingleTask
title:"SingleTask"
FluAppBar{
id:appbar
title:"SingleTask"
width:parent.width
}
FluText{
anchors.centerIn: parent
text:"我是一个SingleTask模式的窗口如果我存在我就激活窗口"
}
}

View File

@ -0,0 +1,31 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
FluWindow {
id:window
width: 500
height: 600
minimumWidth: 500
minimumHeight: 600
maximumWidth: 500
maximumHeight: 600
launchMode: FluWindow.Standard
title:"Standard"
FluAppBar{
id:appbar
title:"Standard"
width:parent.width
}
FluText{
anchors.centerIn: parent
text:"我是一个Standard模式的窗口每次我都会创建一个新的窗口"
}
}

View File

@ -160,5 +160,13 @@
<file>T_StatusView.qml</file>
<file>T_Settings.qml</file>
<file>global/MainEvent.qml</file>
<file>res/svg/home.svg</file>
<file>res/svg/home_dark.svg</file>
<file>page/StandardWindow.qml</file>
<file>page/SingleTaskWindow.qml</file>
<file>page/SingleInstanceWindow.qml</file>
<file>T_RatingControl.qml</file>
<file>res/image/qrcode_wx.jpg</file>
<file>res/image/qrcode_zfb.jpg</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

1
example/res/svg/home.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1681271578882" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3664" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M923.733333 394.666667c-85.333333-70.4-206.933333-174.933333-362.666666-309.333334C533.333333 61.866667 490.666667 61.866667 462.933333 85.333333c-155.733333 134.4-277.333333 238.933333-362.666666 309.333334-14.933333 14.933333-25.6 34.133333-25.6 53.333333 0 38.4 32 70.4 70.4 70.4H192v358.4c0 29.866667 23.466667 53.333333 53.333333 53.333333H405.333333c29.866667 0 53.333333-23.466667 53.333334-53.333333v-206.933333h106.666666v206.933333c0 29.866667 23.466667 53.333333 53.333334 53.333333h160c29.866667 0 53.333333-23.466667 53.333333-53.333333V518.4h46.933333c38.4 0 70.4-32 70.4-70.4 0-21.333333-10.666667-40.533333-25.6-53.333333z m-44.8 59.733333h-57.6c-29.866667 0-53.333333 23.466667-53.333333 53.333333v358.4h-138.666667V661.333333c0-29.866667-23.466667-53.333333-53.333333-53.333333h-128c-29.866667 0-53.333333 23.466667-53.333333 53.333333v206.933334H256V507.733333c0-29.866667-23.466667-53.333333-53.333333-53.333333H145.066667c-4.266667 0-6.4-2.133333-6.4-6.4 0-2.133333 2.133333-4.266667 2.133333-6.4 85.333333-70.4 206.933333-174.933333 362.666667-309.333333 4.266667-4.266667 10.666667-4.266667 14.933333 0 155.733333 134.4 277.333333 238.933333 362.666667 309.333333 2.133333 2.133333 2.133333 2.133333 2.133333 4.266667 2.133333 6.4-2.133333 8.533333-4.266667 8.533333z" fill="#2c2c2c" p-id="3665"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1681277986581" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3875" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M923.733333 394.666667c-85.333333-70.4-206.933333-174.933333-362.666666-309.333334C533.333333 61.866667 490.666667 61.866667 462.933333 85.333333c-155.733333 134.4-277.333333 238.933333-362.666666 309.333334-14.933333 14.933333-25.6 34.133333-25.6 53.333333 0 38.4 32 70.4 70.4 70.4H192v358.4c0 29.866667 23.466667 53.333333 53.333333 53.333333H405.333333c29.866667 0 53.333333-23.466667 53.333334-53.333333v-206.933333h106.666666v206.933333c0 29.866667 23.466667 53.333333 53.333334 53.333333h160c29.866667 0 53.333333-23.466667 53.333333-53.333333V518.4h46.933333c38.4 0 70.4-32 70.4-70.4 0-21.333333-10.666667-40.533333-25.6-53.333333z m-44.8 59.733333h-57.6c-29.866667 0-53.333333 23.466667-53.333333 53.333333v358.4h-138.666667V661.333333c0-29.866667-23.466667-53.333333-53.333333-53.333333h-128c-29.866667 0-53.333333 23.466667-53.333333 53.333333v206.933334H256V507.733333c0-29.866667-23.466667-53.333333-53.333333-53.333333H145.066667c-4.266667 0-6.4-2.133333-6.4-6.4 0-2.133333 2.133333-4.266667 2.133333-6.4 85.333333-70.4 206.933333-174.933333 362.666667-309.333333 4.266667-4.266667 10.666667-4.266667 14.933333 0 155.733333 134.4 277.333333 238.933333 362.666667 309.333333 2.133333 2.133333 2.133333 2.133333 2.133333 4.266667 2.133333 6.4-2.133333 8.533333-4.266667 8.533333z" fill="#ffffff" p-id="3876"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -24,6 +24,7 @@ set(TARGET_SOURCES
FluTheme.cpp
Fluent.cpp
FluentUI.cpp
NativeEventFilter.cpp
WindowHelper.cpp
qml_plugin.cpp
)
@ -37,18 +38,12 @@ set(TARGET_HEADERS
FluTheme.h
Fluent.h
FluentUI.h
FramelessView.h
NativeEventFilter.h
WindowHelper.h
qml_plugin.h
stdafx.h
)
if(WIN32)
set(TARGET_SOURCES ${TARGET_SOURCES} FramelessView_win.cpp)
else()
set(TARGET_SOURCES ${TARGET_SOURCES} FramelessView_unix.cpp)
endif()
add_definitions(-DVERSION_IN="1.0.0")
add_definitions(-DVURI_STR="FluentUI")

View File

@ -7,8 +7,20 @@
#include <QTimer>
#include <QUuid>
#include <QClipboard>
#include "FluTheme.h"
#include "Def.h"
#ifdef Q_OS_WIN
#include <dwmapi.h>
#include <Windows.h>
#include <windowsx.h>
static bool isCompositionEnabled()
{
BOOL composition_enabled = FALSE;
bool success = ::DwmIsCompositionEnabled(&composition_enabled) == S_OK;
return composition_enabled && success;
}
#endif
FluApp* FluApp::m_instance = nullptr;
@ -25,12 +37,16 @@ FluApp::FluApp(QObject *parent)
{
}
void FluApp::init(QWindow *window,QMap<QString, QVariant> properties){
void FluApp::init(QQuickWindow *window){
this->appWindow = window;
this->properties = properties;
}
void FluApp::run(){
#ifdef Q_OS_WIN
if(!isCompositionEnabled()){
FluTheme::getInstance()->frameless(false);
}
#endif
navigate(initialRoute());
}
@ -39,38 +55,45 @@ void FluApp::navigate(const QString& route,const QJsonObject& argument,FluRegist
qErrnoWarning("没有找到当前路由");
return;
}
bool isAppWindow = route == initialRoute();
FramelessView *view = new FramelessView();
QQmlEngine *engine = qmlEngine(appWindow);
QQmlComponent component(engine, routes().value(route).toString());
QVariantMap properties;
properties.insert("route",route);
if(fluRegister){
properties.insert("pageRegister",QVariant::fromValue(fluRegister));
}
properties.insert("argument",argument);
QQuickWindow *view = qobject_cast<QQuickWindow*>(component.createWithInitialProperties(properties));
int launchMode = view->property("launchMode").toInt();
if(launchMode==1){
for (auto& pair : wnds) {
QString r = pair->property("route").toString();
if(r == route){
pair->requestActivate();
view->deleteLater();
return;
}
}
}else if(launchMode==2){
for (auto& pair : wnds) {
QString r = pair->property("route").toString();
if(r == route){
pair->close();
break;
}
}
}
if(FluTheme::getInstance()->frameless()){
view->setFlag(Qt::FramelessWindowHint,true);
}
wnds.insert(view->winId(),view);
if(fluRegister){
fluRegister->to(view);
view->setProperty("pageRegister",QVariant::fromValue(fluRegister));
}
view->setProperty("argument",argument);
QMapIterator<QString, QVariant> iterator(properties);
while (iterator.hasNext()) {
iterator.next();
QString key = iterator.key();
QVariant value = iterator.value();
view->engine()->rootContext()->setContextProperty(key,value);
}
view->setColor(QColor(Qt::transparent));
QObject::connect(view, &QQuickView::statusChanged, view, [&](QQuickView::Status status) {
if (status == QQuickView::Status::Ready) {
Q_EMIT windowReady(view);
view->moveToScreenCenter();
view->show();
}
});
view->setSource((routes().value(route).toString()));
if(isAppWindow){
QObject::connect(view->engine(), &QQmlEngine::quit, qApp, &QCoreApplication::quit);
}else{
view->closeDeleteLater();
}
}
bool FluApp::equalsWindow(FramelessView *view,QWindow *window){
return view->winId() == window->winId();
}
QJsonArray FluApp::awesomelist(const QString& keyword)
@ -104,3 +127,7 @@ void FluApp::clipText(const QString& text){
QString FluApp::uuid(){
return QUuid::createUuid().toString();
}
void FluApp::closeApp(){
qApp->exit(0);
}

View File

@ -8,7 +8,6 @@
#include <QJsonObject>
#include <QQmlEngine>
#include "FluRegister.h"
#include "FramelessView.h"
#include "stdafx.h"
class FluApp : public QObject
@ -27,11 +26,7 @@ public:
Q_INVOKABLE void navigate(const QString& route,const QJsonObject& argument = {},FluRegister* fluRegister = nullptr);
Q_INVOKABLE void init(QWindow *window,QMap<QString, QVariant> properties);
Q_SIGNAL void windowReady(FramelessView *view);
Q_INVOKABLE bool equalsWindow(FramelessView *view,QWindow *window);
Q_INVOKABLE void init(QQuickWindow *window);
Q_INVOKABLE QJsonArray awesomelist(const QString& keyword = "");
@ -39,11 +34,13 @@ public:
Q_INVOKABLE QString uuid();
Q_INVOKABLE void closeApp();
public:
QMap<quint64, QQuickWindow*> wnds;
private:
QMap<QString, QVariant> properties;
static FluApp* m_instance;
QWindow *appWindow;
};
#endif // FLUAPP_H

View File

@ -2,15 +2,15 @@
#define FLUREGISTER_H
#include <QObject>
#include <FramelessView.h>
#include <QQuickWindow>
#include <QJsonObject>
#include "stdafx.h"
class FluRegister : public QObject
{
Q_OBJECT
Q_PROPERTY_AUTO(FramelessView*,from)
Q_PROPERTY_AUTO(FramelessView*,to)
Q_PROPERTY_AUTO(QQuickWindow*,from)
Q_PROPERTY_AUTO(QQuickWindow*,to)
Q_PROPERTY_AUTO(QString,path);
public:
explicit FluRegister(QObject *parent = nullptr);

View File

@ -1,6 +1,8 @@
#include "FluTheme.h"
#include "FluColors.h"
#include <QPalette>
#include <QGuiApplication>
FluTheme* FluTheme::m_instance = nullptr;
@ -19,5 +21,13 @@ FluTheme::FluTheme(QObject *parent)
textSize(13);
nativeText(true);
frameless(true);
dark(false);
std::function<bool()> isDark = [](){
QPalette palette = (qobject_cast<QGuiApplication *>(QCoreApplication::instance()))->palette();
QColor color = palette.color(QPalette::Window).rgb();
return !(color.red() * 0.2126 + color.green() * 0.7152 + color.blue() * 0.0722 > 255 / 2);
};
dark(isDark());
connect(qobject_cast<QGuiApplication *>(QCoreApplication::instance()), &QGuiApplication::paletteChanged, this, [=] (const QPalette &) {
dark(isDark());
});
}

View File

@ -5,6 +5,7 @@
#include <QGuiApplication>
#include <QQuickWindow>
#include "FluColors.h"
#include "NativeEventFilter.h"
#include "FluTheme.h"
#include "WindowHelper.h"
#include "FluApp.h"
@ -33,6 +34,7 @@ void Fluent::registerTypes(const char *uri){
qmlRegisterType<WindowHelper>(uri,major,minor,"WindowHelper");
qmlRegisterType<FluColorSet>(uri,major,minor,"FluColorSet");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluRatingControl.qml"),uri,major,minor,"FluRatingControl");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluStatusView.qml"),uri,major,minor,"FluStatusView");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluPagination.qml"),uri,major,minor,"FluPagination");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluToggleButton.qml"),uri,major,minor,"FluToggleButton");
@ -95,6 +97,8 @@ void Fluent::registerTypes(const char *uri){
void Fluent::initializeEngine(QQmlEngine *engine, const char *uri)
{
nativeEvent = new NativeEventFilter();
qApp->installNativeEventFilter(nativeEvent);
Q_UNUSED(engine)
Q_UNUSED(uri)
#ifdef Q_OS_WIN

View File

@ -3,17 +3,25 @@
#include <QObject>
#include <QQmlEngine>
#include "NativeEventFilter.h"
class Fluent: public QObject
{
Q_OBJECT
public:
Q_INVOKABLE QString version() const;
~Fluent(){
if (nativeEvent != Q_NULLPTR) {
delete nativeEvent;
nativeEvent = Q_NULLPTR;
}
}
void registerTypes(const char *uri);
void initializeEngine(QQmlEngine *engine, const char *uri);
static Fluent *getInstance();
private:
static Fluent* m_instance;
NativeEventFilter *nativeEvent = Q_NULLPTR;
};
#endif // FLUENT_H

View File

@ -19,7 +19,7 @@ HEADERS += \
FluTheme.h \
Fluent.h \
FluentUI.h \
FramelessView.h \
NativeEventFilter.h \
WindowHelper.h \
qml_plugin.h \
stdafx.h
@ -33,16 +33,12 @@ SOURCES += \
FluTheme.cpp \
Fluent.cpp \
FluentUI.cpp \
NativeEventFilter.cpp \
WindowHelper.cpp \
qml_plugin.cpp \
win32 {
LIBS += -ldwmapi -luser32
SOURCES += \
FramelessView_win.cpp
} else {
SOURCES += \
FramelessView_unix.cpp
}
DEFINES += VERSION_IN=\\\"1.0.0\\\"

View File

@ -1,56 +0,0 @@
#pragma once
#include <QMouseEvent>
#include <QQuickView>
#include <QRegion>
class FramelessViewPrivate;
class FramelessView : public QQuickView
{
Q_OBJECT
using Super = QQuickView;
Q_PROPERTY(bool isMax READ isMax NOTIFY isMaxChanged)
Q_PROPERTY(bool isFull READ isFull NOTIFY isFullChanged)
public:
explicit FramelessView(QWindow *parent = nullptr);
~FramelessView();
void moveToScreenCenter();
void closeDeleteLater();
bool isMax() const;
bool isFull() const;
QQuickItem *titleItem() const;
static QMap<WId,FramelessView*> *windowCache;
static QRect calcCenterGeo(const QRect &screenGeo, const QSize &normalSize);
public slots:
void setIsMax(bool isMax);
void setIsFull(bool isFull);
void setTitleItem(QQuickItem* item);
signals:
void isMaxChanged(bool isMax);
void isFullChanged(bool isFull);
void mousePressed(int xPos, int yPos, int button);
protected:
void showEvent(QShowEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
bool event(QEvent *ev) override;
# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override;
# else
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
# endif
void mousePressEvent(QMouseEvent* event) override
{
# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
emit mousePressed(event->position().x(), event->position().y(), event->button());
#else
emit mousePressed(event->x(), event->y(), event->button());
#endif
Super::mousePressEvent(event);
}
private:
FramelessViewPrivate *d;
};

View File

@ -1,138 +0,0 @@
#include "FramelessView.h"
#include <QGuiApplication>
#include <QQuickItem>
#include <QScreen>
#include <QWindow>
#include <FluTheme.h>
class FramelessViewPrivate
{
public:
bool m_isMax = false;
bool m_isFull = false;
bool m_deleteLater = false;
QQuickItem *m_titleItem = nullptr;
};
FramelessView::FramelessView(QWindow *parent) : Super(parent), d(new FramelessViewPrivate)
{
if(FluTheme::getInstance()->frameless()){
setFlags( Qt::Window | Qt::FramelessWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
}
setResizeMode(SizeRootObjectToView);
setIsMax(windowState() == Qt::WindowMaximized);
setIsFull(windowState() == Qt::WindowFullScreen);
connect(this, &QWindow::windowStateChanged, this, [&](Qt::WindowState state) {
(void)state;
setIsMax(windowState() == Qt::WindowMaximized);
setIsFull(windowState() == Qt::WindowFullScreen);
});
connect(FluTheme::getInstance(),&FluTheme::framelessChanged,this,[=](){
setFlag(Qt::Window,false);
setFlag(Qt::Window,true);
});
}
FramelessView::~FramelessView()
{
delete d;
}
void FramelessView::showEvent(QShowEvent *e)
{
Super::showEvent(e);
}
QRect FramelessView::calcCenterGeo(const QRect &screenGeo, const QSize &normalSize)
{
int w = normalSize.width();
int h = normalSize.height();
int x = screenGeo.x() + (screenGeo.width() - w) / 2;
int y = screenGeo.y() + (screenGeo.height() - h) / 2;
if (screenGeo.width() < w) {
x = screenGeo.x();
w = screenGeo.width();
}
if (screenGeo.height() < h) {
y = screenGeo.y();
h = screenGeo.height();
}
return { x, y, w, h };
}
void FramelessView::moveToScreenCenter()
{
auto geo = calcCenterGeo(screen()->availableGeometry(), size());
if (minimumWidth() > geo.width() || minimumHeight() > geo.height()) {
setMinimumSize(geo.size());
}
setGeometry(geo);
update();
}
void FramelessView::closeDeleteLater(){
d->m_deleteLater = true;
}
bool FramelessView::isMax() const
{
return d->m_isMax;
}
bool FramelessView::isFull() const
{
return d->m_isFull;
}
QQuickItem *FramelessView::titleItem() const
{
return d->m_titleItem;
}
void FramelessView::setIsMax(bool isMax)
{
if (d->m_isMax == isMax)
return;
d->m_isMax = isMax;
emit isMaxChanged(d->m_isMax);
}
void FramelessView::setIsFull(bool isFull)
{
if(d->m_isFull == isFull)
return;
d->m_isFull = isFull;
emit isFullChanged(d->m_isFull);
}
void FramelessView::setTitleItem(QQuickItem *item)
{
d->m_titleItem = item;
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool FramelessView::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
#else
bool FramelessView::nativeEvent(const QByteArray &eventType, void *message, long *result)
#endif
{
return Super::nativeEvent(eventType, message, result);
}
void FramelessView::resizeEvent(QResizeEvent *e)
{
Super::resizeEvent(e);
}
bool FramelessView::event(QEvent *ev)
{
if (ev->type() == QEvent::Close) {
if(d->m_deleteLater){
deleteLater();
ev->setAccepted(false);
}
}
return QQuickWindow::event(ev);
}

View File

@ -1,268 +0,0 @@
#include "FramelessView.h"
#include <QGuiApplication>
#include <QQuickItem>
#include <QScreen>
#include <QWindow>
#include <FluTheme.h>
#include <QTimer>
#include <dwmapi.h>
#include <windowsx.h>
#pragma comment(lib, "Dwmapi.lib")
#pragma comment(lib, "User32.lib")
static bool isCompositionEnabled()
{
BOOL composition_enabled = FALSE;
bool success = ::DwmIsCompositionEnabled(&composition_enabled) == S_OK;
return composition_enabled && success;
}
static bool isMaxWin(QWindow* win)
{
return win->windowState() == Qt::WindowMaximized;
}
static bool isFullWin(QQuickView* win)
{
return win->windowState() == Qt::WindowFullScreen;
}
static bool isFixWin(QQuickView* win)
{
return win->minimumWidth() == win->maximumWidth() && win->minimumHeight() == win->maximumHeight();
}
static long hitTest(RECT winrect, long x, long y, int borderWidth)
{
if ((x >= winrect.left) && (x < winrect.left + borderWidth) && (y >= winrect.top) && (y < winrect.top + borderWidth))
{
return HTTOPLEFT;
}
else if (x < winrect.right && x >= winrect.right - borderWidth && y >= winrect.top && y < winrect.top + borderWidth)
{
return HTTOPRIGHT;
}
else if (x >= winrect.left && x < winrect.left + borderWidth && y < winrect.bottom && y >= winrect.bottom - borderWidth)
{
return HTBOTTOMLEFT;
}
else if (x < winrect.right && x >= winrect.right - borderWidth && y < winrect.bottom && y >= winrect.bottom - borderWidth)
{
return HTBOTTOMRIGHT;
}
else if (x >= winrect.left && x < winrect.left + borderWidth)
{
return HTLEFT;
}
else if (x < winrect.right && x >= winrect.right - borderWidth)
{
return HTRIGHT;
}
else if (y >= winrect.top && y < winrect.top + borderWidth)
{
return HTTOP;
}
else if (y < winrect.bottom && y >= winrect.bottom - borderWidth)
{
return HTBOTTOM;
}
else
{
return 0;
}
}
class FramelessViewPrivate
{
public:
bool m_isMax = false;
bool m_isFull = false;
bool m_deleteLater = false;
bool m_isFirst = true;
QQuickItem *m_titleItem = nullptr;
};
FramelessView::FramelessView(QWindow *parent) : Super(parent), d(new FramelessViewPrivate)
{
if(!isCompositionEnabled()){
FluTheme::getInstance()->frameless(false);
}
if(FluTheme::getInstance()->frameless()){
setFlag(Qt::FramelessWindowHint,true);
}
setResizeMode(SizeRootObjectToView);
setIsMax(windowState() == Qt::WindowMaximized);
setIsFull(windowState() == Qt::WindowFullScreen);
connect(this, &QWindow::windowStateChanged, this, [=](Qt::WindowState state) {
(void)state;
setIsMax(windowState() == Qt::WindowMaximized);
setIsFull(windowState() == Qt::WindowFullScreen);
});
connect(FluTheme::getInstance(),&FluTheme::framelessChanged,this,[=](){
setFlag(Qt::Window,false);
setFlag(Qt::Window,true);
});
}
FramelessView::~FramelessView()
{
delete d;
}
void FramelessView::showEvent(QShowEvent *e)
{
static const MARGINS shadow_state[2] { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } };
::DwmExtendFrameIntoClientArea((HWND)(winId()), &shadow_state[true]);
if(FluTheme::getInstance()->frameless()){
setFlag(Qt::FramelessWindowHint,false);
}
Super::showEvent(e);
}
QRect FramelessView::calcCenterGeo(const QRect &screenGeo, const QSize &normalSize)
{
int w = normalSize.width();
int h = normalSize.height();
int x = screenGeo.x() + (screenGeo.width() - w) / 2;
int y = screenGeo.y() + (screenGeo.height() - h) / 2;
if (screenGeo.width() < w) {
x = screenGeo.x();
w = screenGeo.width();
}
if (screenGeo.height() < h) {
y = screenGeo.y();
h = screenGeo.height();
}
return { x, y, w, h };
}
void FramelessView::moveToScreenCenter()
{
auto geo = calcCenterGeo(screen()->availableGeometry(), size());
if (minimumWidth() > geo.width() || minimumHeight() > geo.height()) {
setMinimumSize(geo.size());
}
setGeometry(geo);
update();
}
void FramelessView::closeDeleteLater(){
d->m_deleteLater = true;
}
bool FramelessView::isMax() const
{
return d->m_isMax;
}
bool FramelessView::isFull() const
{
return d->m_isFull;
}
QQuickItem *FramelessView::titleItem() const
{
return d->m_titleItem;
}
void FramelessView::setIsMax(bool isMax)
{
if (d->m_isMax == isMax)
return;
d->m_isMax = isMax;
emit isMaxChanged(d->m_isMax);
}
void FramelessView::setIsFull(bool isFull)
{
if(d->m_isFull == isFull)
return;
d->m_isFull = isFull;
emit isFullChanged(d->m_isFull);
}
int count = 1;
void FramelessView::setTitleItem(QQuickItem *item)
{
d->m_titleItem = item;
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool FramelessView::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
#else
bool FramelessView::nativeEvent(const QByteArray &eventType, void *message, long *result)
#endif
{
MSG* msg = static_cast<MSG*>(message);
if (!msg || !msg->hwnd)
{
return false;
}
if (msg->message == WM_NCHITTEST && FluTheme::getInstance()->frameless())
{
RECT winrect;
GetWindowRect(HWND(winId()), &winrect);
long x = GET_X_LPARAM(msg->lParam);
long y = GET_Y_LPARAM(msg->lParam);
*result = 0;
if (!isMaxWin(this) && !isFullWin(this) && !isFixWin(this))
{
*result = hitTest(winrect, x, y, 4);
if (0 != *result)
{
return true;
}
}
}else if (msg->message == WM_NCCALCSIZE && FluTheme::getInstance()->frameless())
{
const auto mode = static_cast<BOOL>(msg->wParam);
const auto clientRect = mode ? &(reinterpret_cast<LPNCCALCSIZE_PARAMS>(msg->lParam)->rgrc[0]) : reinterpret_cast<LPRECT>(msg->lParam);
if (mode == TRUE)
{
*result = WVR_REDRAW;
if (!isMaxWin(this) && !isFullWin(this))
{
if (clientRect->top != 0)
{
clientRect->top -= 0.1;
}
}
else
{
if (clientRect->top != 0)
{
clientRect->top += 0.1;
}
}
return true;
}
}else if (msg->message == WM_WINDOWPOSCHANGING)
{
WINDOWPOS* wp = reinterpret_cast<WINDOWPOS*>(msg->lParam);
if (wp != nullptr && (wp->flags & SWP_NOSIZE) == 0)
{
wp->flags |= SWP_NOCOPYBITS;
*result = 0;
return true;
}
}
return Super::nativeEvent(eventType, message, result);
}
void FramelessView::resizeEvent(QResizeEvent *e)
{
Super::resizeEvent(e);
}
bool FramelessView::event(QEvent *ev)
{
if (ev->type() == QEvent::Close) {
if(d->m_deleteLater){
deleteLater();
ev->setAccepted(false);
}
}
return QQuickWindow::event(ev);
}

76
src/NativeEventFilter.cpp Normal file
View File

@ -0,0 +1,76 @@
#include "NativeEventFilter.h"
#include "FluTheme.h"
#include "FluApp.h"
#ifdef Q_OS_WIN
#include <Windows.h>
#include <windowsx.h>
#endif
bool NativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result)
{
#ifdef Q_OS_WIN
if (eventType == "windows_generic_MSG" && FluTheme::getInstance()->frameless()) {
MSG* msg = static_cast<MSG *>(message);
if (msg == Q_NULLPTR)
return false;
switch(msg->message) {
case WM_NCCALCSIZE:{
NCCALCSIZE_PARAMS& params = *reinterpret_cast<NCCALCSIZE_PARAMS*>(msg->lParam);
if (params.rgrc[0].top != 0)
params.rgrc[0].top -= 1;
*result = WVR_REDRAW;
return true;
}
case WM_NCHITTEST: {
auto view = FluApp::getInstance()->wnds[(WId)msg->hwnd];
bool isResize = !(view->maximumWidth()==view->minimumWidth()&&view->maximumHeight()==view->minimumHeight());
const LONG borderWidth = 8;
RECT winrect;
GetWindowRect(msg->hwnd, &winrect);
long x = GET_X_LPARAM(msg->lParam);
long y = GET_Y_LPARAM(msg->lParam);
if (x >= winrect.left && x < winrect.left + borderWidth &&
y < winrect.bottom && y >= winrect.bottom - borderWidth && isResize) {
*result = HTBOTTOMLEFT;
return true;
}
if (x < winrect.right && x >= winrect.right - borderWidth &&
y < winrect.bottom && y >= winrect.bottom - borderWidth && isResize) {
*result = HTBOTTOMRIGHT;
return true;
}
if (x >= winrect.left && x < winrect.left + borderWidth &&
y >= winrect.top && y < winrect.top + borderWidth && isResize) {
*result = HTTOPLEFT;
return true;
}
if (x < winrect.right && x >= winrect.right - borderWidth &&
y >= winrect.top && y < winrect.top + borderWidth && isResize) {
*result = HTTOPRIGHT;
return true;
}
if (x >= winrect.left && x < winrect.left + borderWidth && isResize) {
*result = HTLEFT;
return true;
}
if (x < winrect.right && x >= winrect.right - borderWidth && isResize) {
*result = HTRIGHT;
return true;
}
if (y < winrect.bottom && y >= winrect.bottom - borderWidth && isResize) {
*result = HTBOTTOM;
return true;
}
if (y >= winrect.top && y < winrect.top + borderWidth && isResize) {
*result = HTTOP;
return true;
}
return false;
}
default:
break;
}
}
#endif
return false;
}

14
src/NativeEventFilter.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef NATIVEEVENTFILTER_H
#define NATIVEEVENTFILTER_H
#include <QObject>
#include <QAbstractNativeEventFilter>
class NativeEventFilter : public QAbstractNativeEventFilter
{
public:
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override;
};
#endif // NATIVEEVENTFILTER_H

View File

@ -1,6 +1,19 @@
#include "WindowHelper.h"
#include "FluRegister.h"
#include "FluApp.h"
#include "FluTheme.h"
#ifdef Q_OS_WIN
#include <dwmapi.h>
#include <Windows.h>
#include <windowsx.h>
enum class Style : DWORD
{
windowed = (WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CLIPCHILDREN),
aero_borderless = (WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CLIPCHILDREN)
};
#endif
WindowHelper::WindowHelper(QObject *parent)
: QObject{parent}
@ -8,56 +21,38 @@ WindowHelper::WindowHelper(QObject *parent)
}
void WindowHelper::setTitle(const QString& text){
window->setTitle(text);
}
void WindowHelper::initWindow(FramelessView* window){
void WindowHelper::initWindow(QQuickWindow* window){
this->window = window;
}
QJsonObject WindowHelper::getArgument(){
return window->property("argument").toJsonObject();
}
QVariant WindowHelper::getPageRegister(){
return window->property("pageRegister");
}
void WindowHelper::setMinimumWidth(int width){
this->window->setMinimumWidth(width);
}
void WindowHelper::setMaximumWidth(int width){
this->window->setMaximumWidth(width);
}
void WindowHelper::setMinimumHeight(int height){
this->window->setMinimumHeight(height);
}
void WindowHelper::setMaximumHeight(int height){
this->window->setMaximumHeight(height);
}
void WindowHelper::updateWindow(){
this->window->setFlag(Qt::Window,false);
this->window->setFlag(Qt::Window,true);
}
void WindowHelper::setOpacity(qreal opacity){
this->window->setOpacity(opacity);
}
void WindowHelper::setModality(int type){
if(type == 0){
this->window->setModality(Qt::NonModal);
}else if(type == 1){
this->window->setModality(Qt::WindowModal);
}else if(type == 2){
this->window->setModality(Qt::ApplicationModal);
}else{
this->window->setModality(Qt::NonModal);
void WindowHelper::firstUpdate(){
if(isFisrt){
#ifdef Q_OS_WIN
if(FluTheme::getInstance()->frameless()){
HWND wnd = (HWND)window->winId();
SetWindowLongPtr(wnd, GWL_STYLE, static_cast<LONG>(Style::aero_borderless));
const MARGINS shadow_on = { 1, 1, 1, 1 };
DwmExtendFrameIntoClientArea(wnd, &shadow_on);
SetWindowPos(wnd, Q_NULLPTR, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
ShowWindow(wnd, SW_SHOW);
window->setFlag(Qt::FramelessWindowHint,false);
}
#endif
isFisrt = false;
}
}
QVariant WindowHelper::createRegister(const QString& path){
FluRegister *p = new FluRegister(this->window);
p->from(this->window);
QVariant WindowHelper::createRegister(QQuickWindow* window,const QString& path){
FluRegister *p = new FluRegister(window);
p->from(window);
p->path(path);
return QVariant::fromValue(p);
}
void WindowHelper::destoryWindow(){
if(this->window){
FluApp::getInstance()->wnds.remove(this->window->winId());
this->window->deleteLater();
}
}

View File

@ -6,7 +6,6 @@
#include <QQuickItem>
#include <QWindow>
#include <QJsonObject>
#include "FramelessView.h"
class WindowHelper : public QObject
{
@ -15,22 +14,15 @@ class WindowHelper : public QObject
public:
explicit WindowHelper(QObject *parent = nullptr);
Q_INVOKABLE void initWindow(FramelessView* window);
Q_INVOKABLE void setTitle(const QString& text);
Q_INVOKABLE void setMinimumWidth(int width);
Q_INVOKABLE void setMaximumWidth(int width);
Q_INVOKABLE void setMinimumHeight(int height);
Q_INVOKABLE void setMaximumHeight(int height);
Q_INVOKABLE QJsonObject getArgument();
Q_INVOKABLE QVariant getPageRegister();
Q_INVOKABLE void updateWindow();
Q_INVOKABLE void setOpacity(qreal opacity);
Q_INVOKABLE void setModality(int type);
Q_INVOKABLE QVariant createRegister(const QString& path);
Q_INVOKABLE void initWindow(QQuickWindow* window);
Q_INVOKABLE void destoryWindow();
Q_INVOKABLE QVariant createRegister(QQuickWindow* window,const QString& path);
Q_INVOKABLE void firstUpdate();
private:
FramelessView* window;
QQuickWindow* window;
bool isFisrt=true;
};
#endif // WINDOWHELPER_H

View File

@ -67,7 +67,6 @@ Rectangle{
height: root.height
spacing: 0
RowLayout{
Layout.alignment: Qt.AlignVCenter
Layout.rightMargin: 5

View File

@ -67,21 +67,26 @@ Rectangle {
modal: true
dim:false
enter: Transition {
NumberAnimation {
property: "y"
from:0
to:popup.y
duration: 150
}
reversible: true
NumberAnimation {
property: "opacity"
from:0
to:1
duration: 150
duration: 83
}
}
exit:Transition {
NumberAnimation {
property: "opacity"
from:1
to:0
duration: 83
}
}
contentItem: Item{
anchors.fill: parent
clip: true
FluCalendarView{
id:container
onDateClicked:
@ -94,15 +99,19 @@ Rectangle {
}
}
}
background: Item{}
background: Item{
FluShadow{
radius: 5
}
}
function showPopup() {
var pos = control.mapToItem(null, 0, 0)
if(window.height>pos.y+control.height+popup.height){
if(window.height>pos.y+control.height+container.height){
popup.y = control.height
} else if(pos.y>popup.height){
popup.y = -popup.height
} else if(pos.y>container.height){
popup.y = -container.height
} else {
popup.y = window.height-(pos.y+popup.height)
popup.y = window.height-(pos.y+container.height)
}
popup.x = -(popup.width-control.width)/2
popup.open()

View File

@ -33,34 +33,42 @@ FluControl{
height: container.height
width: container.width
contentItem: Item{
anchors.fill: parent
clip: true
FluColorView{
id:container
}
}
background:Item{}
enter: Transition {
NumberAnimation {
property: "y"
from:0
to:popup.y
duration: 150
background:Item{
FluShadow{
radius: 5
}
}
enter: Transition {
reversible: true
NumberAnimation {
property: "opacity"
from:0
to:1
duration: 150
duration: 83
}
}
exit:Transition {
NumberAnimation {
property: "opacity"
from:1
to:0
duration: 83
}
}
function showPopup() {
var pos = control.mapToItem(null, 0, 0)
if(window.height>pos.y+control.height+popup.height){
if(window.height>pos.y+control.height+container.height){
popup.y = control.height
} else if(pos.y>popup.height){
popup.y = -popup.height
} else if(pos.y>container.height){
popup.y = -container.height
} else {
popup.y = window.height-(pos.y+popup.height)
popup.y = window.height-(pos.y+container.height)
}
popup.x = -(popup.width-control.width)/2
popup.open()

View File

@ -100,28 +100,39 @@ Rectangle {
Menu{
id:popup
modal: true
width: 300
height: 340
width: container.width
height: container.height
dim:false
enter: Transition {
NumberAnimation {
property: "y"
from:0
to:popup.y
duration: 150
}
reversible: true
NumberAnimation {
property: "opacity"
from:0
to:1
duration: 150
duration: 83
}
}
background:Item{}
contentItem: Rectangle{
exit:Transition {
NumberAnimation {
property: "opacity"
from:1
to:0
duration: 83
}
}
background:Item{
FluShadow{
radius: 4
}
}
contentItem: Item{
clip: true
Rectangle{
id:container
radius: 4
anchors.fill: parent
width: 300
height: 340
color: FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1)
MouseArea{
anchors.fill: parent
@ -338,6 +349,7 @@ Rectangle {
}
}
}
}
y:35
function showPopup() {
changeFlag = true
@ -362,12 +374,12 @@ Rectangle {
text_day.text = day
var pos = root.mapToItem(null, 0, 0)
if(window.height>pos.y+root.height+popup.height){
if(window.height>pos.y+root.height+container.height){
popup.y = root.height
} else if(pos.y>popup.height){
popup.y = -popup.height
} else if(pos.y>container.height){
popup.y = -container.height
} else {
popup.y = window.height-(pos.y+popup.height)
popup.y = window.height-(pos.y+container.height)
}
popup.open()
}

View File

@ -76,12 +76,13 @@ FluControl {
onClicked: {
var pos = control.mapToItem(null, 0, 0)
if(window.height>pos.y+control.height+menu.height){
var containerHeight = menu.getContainerHeight()
if(window.height>pos.y+control.height+containerHeight){
menu.y = control.height
}else if(pos.y>menu.height){
menu.y = -menu.height
}else if(pos.y>containerHeight){
menu.y = -containerHeight
}else{
menu.y = window.height-(pos.y+menu.height)
menu.y = window.height-(pos.y+containerHeight)
}
menu.open()
}

View File

@ -84,7 +84,9 @@ Item {
height: expand ? contentHeight : 0
Behavior on height {
NumberAnimation{
duration: 150
duration: 167
easing.type: Easing.Bezier
easing.bezierCurve: expand ? [ 0, 0, 0, 1 ] : [ 1, 0, 0, 0 ]
}
}
}

View File

@ -38,6 +38,7 @@ FluControl {
id:control
width: 30
height: 30
clip: true
implicitWidth: width
implicitHeight: height
padding: 0

View File

@ -12,38 +12,50 @@ Menu {
modal:true
dim:false
enter: Transition {
NumberAnimation {
property: "y"
from:0
to:popup.y
duration: animEnabled ? 150 : 0
}
reversible: true
NumberAnimation {
property: "opacity"
from:0
to:1
duration: animEnabled ? 150 : 0
duration: 83
}
}
exit:Transition {
NumberAnimation {
property: "opacity"
from:1
to:0
duration: 83
}
}
background:Item{
FluShadow{
radius: 5
}
}
background:Item{}
contentItem: Item {
clip: true
Rectangle{
anchors.fill: parent
color:FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,0.97) : Qt.rgba(237/255,237/255,237/255,0.97)
radius: 5
}
FluShadow{
radius: 5
}
Column{
id:container
spacing: 5
topPadding: 5
bottomPadding: 5
width: popup.width
id:container
function closePopup(){
popup.close()
}
}
}
function getContainerHeight(){
return container.height
}
}

View File

@ -120,7 +120,9 @@ Item {
}
Behavior on height {
NumberAnimation{
duration: 150
duration: 167
easing.type: Easing.Bezier
easing.bezierCurve: [ 0, 0, 0, 1 ]
}
}
}
@ -137,7 +139,9 @@ Item {
}
Behavior on height {
NumberAnimation{
duration: 150
duration: 167
easing.type: Easing.Bezier
easing.bezierCurve: [ 0, 0, 0, 1 ]
}
}
width: layout_list.width
@ -206,12 +210,12 @@ Item {
visible:opacity
Behavior on opacity {
NumberAnimation{
duration: 220
duration: 83
}
}
Behavior on rotation {
NumberAnimation{
duration: 150
duration: 83
}
}
}
@ -246,22 +250,37 @@ Item {
return Qt.rgba(0,0,0,0)
}
}
Component{
id:com_icon
FluIcon{
id:item_icon
iconSource: {
if(model.icon){
return model.icon
}
return 0
}
iconSize: 15
}
}
Item{
id:item_icon
width: 30
height: 30
iconSize: 15
anchors{
verticalCenter: parent.verticalCenter
left:parent.left
leftMargin: 3
}
Loader{
anchors.centerIn: parent
sourceComponent: {
if(model.cusIcon){
return model.cusIcon
}
return com_icon
}
}
}
FluText{
id:item_title
@ -275,7 +294,7 @@ Item {
visible:opacity
Behavior on opacity {
NumberAnimation{
duration: 220
duration: 83
}
}
anchors{
@ -298,7 +317,9 @@ Item {
Item{
Behavior on height {
NumberAnimation{
duration: 150
duration: 167
easing.type: Easing.Bezier
easing.bezierCurve: [ 0, 0, 0, 1 ]
}
}
clip: true
@ -382,23 +403,39 @@ Item {
return Qt.rgba(0,0,0,0)
}
}
Component{
id:com_icon
FluIcon{
id:item_icon
iconSource: {
if(model.icon){
return model.icon
}
return 0
}
iconSize: 15
}
}
Item{
id:item_icon
width: 30
height: 30
iconSize: 15
anchors{
verticalCenter: parent.verticalCenter
left:parent.left
leftMargin: 3
}
Loader{
anchors.centerIn: parent
sourceComponent: {
if(model.cusIcon){
return model.cusIcon
}
return com_icon
}
}
}
FluText{
id:item_title
text:model.title
@ -411,7 +448,7 @@ Item {
visible:opacity
Behavior on opacity {
NumberAnimation{
duration: 220
duration: 83
}
}
color:{
@ -465,13 +502,19 @@ Item {
id:btn_nav
iconSource: FluentIcons.GlobalNavButton
iconSize: 15
Layout.preferredWidth: 40
Layout.preferredWidth: d.isMinimal ? 40 : 0
Layout.preferredHeight: 40
visible: d.isMinimal
Layout.alignment: Qt.AlignVCenter
onClicked: {
d.enableNavigationPanel = !d.enableNavigationPanel
}
Behavior on Layout.preferredWidth{
NumberAnimation{
duration: 167
easing.type: Easing.Bezier
easing.bezierCurve: [ 0, 0, 0, 1 ]
}
}
}
Image{
id:image_logo
@ -509,10 +552,24 @@ Item {
clip: true
popEnter : Transition{}
popExit : Transition {
NumberAnimation { properties: "y"; from: 0; to: nav_swipe.height; duration: 200 }
NumberAnimation {
properties: "y"
from: 0
to: nav_swipe.height
duration: 167
easing.type: Easing.Bezier
easing.bezierCurve: [ 1, 0, 0, 0 ]
}
}
pushEnter: Transition {
NumberAnimation { properties: "y"; from: nav_swipe.height; to: 0; duration: 200 }
NumberAnimation {
properties: "y";
from: nav_swipe.height;
to: 0
duration: 167
easing.type: Easing.Bezier
easing.bezierCurve: [ 0, 0, 0, 1 ]
}
}
pushExit : Transition{}
replaceEnter : Transition{}
@ -538,13 +595,17 @@ Item {
}
Behavior on width{
NumberAnimation{
duration: 150
duration: 167
easing.type: Easing.Bezier
easing.bezierCurve: [ 0, 0, 0, 1 ]
}
}
Behavior on x{
id:anim_layout_list_x
NumberAnimation{
duration: 150
duration: 167
easing.type: Easing.Bezier
easing.bezierCurve: [ 0, 0, 0, 1 ]
}
}
anchors{
@ -582,16 +643,28 @@ Item {
id:loader_auto_suggest_box
anchors.centerIn: parent
sourceComponent: autoSuggestBox
visible: {
opacity: {
if(d.isCompactAndNotPanel){
return false
}
return true
}
visible: opacity
Behavior on opacity{
NumberAnimation{
duration: 83
}
}
}
FluIconButton{
visible:d.isCompactAndNotPanel
visible:opacity
opacity:d.isCompactAndNotPanel
Behavior on opacity{
NumberAnimation{
duration: 83
}
}
hoverColor: FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03)
pressedColor: FluTheme.dark ? Qt.rgba(1,1,1,0.03) : Qt.rgba(0,0,0,0.03)
normalColor: FluTheme.dark ? Qt.rgba(0,0,0,0) : Qt.rgba(0,0,0,0)
@ -727,7 +800,7 @@ Item {
property: "opacity"
from:0
to:1
duration: 150
duration: 83
}
}
background: Rectangle{
@ -804,6 +877,7 @@ Item {
function setCurrentIndex(index){
nav_list.currentIndex = index
}
function getItems(){
@ -818,4 +892,21 @@ Item {
return nav_list.currentIndex
}
function startPageByItem(data){
var items = getItems();
for(var i=0;i<items.length;i++){
var item = items[i]
if(item.key === data.key){
if(getCurrentIndex() === i){
return
}
setCurrentIndex(i)
if(item.parent && !d.isCompactAndNotPanel){
item.parent.isExpand = true
}
return
}
}
}
}

View File

@ -7,6 +7,7 @@ QtObject {
property string title
property int order : 0
property int icon
property Component cusIcon
property bool recentlyAdded: false
property bool recentlyUpdated: false
property string desc

View File

@ -4,7 +4,8 @@ import FluentUI
FluObject {
readonly property string key : FluApp.uuid()
property string title
property int icon
property var icon
property Component cusIcon
property bool isExpand: false
property var parent
property int idx

View File

@ -7,6 +7,7 @@ Item {
id:control
default property alias content: d.children
property alias currentIndex: nav_list.currentIndex
property color normalColor: FluTheme.dark ? FluColors.Grey120 : FluColors.Grey120
property color hoverColor: FluTheme.dark ? FluColors.Grey10 : FluColors.Black

View File

@ -0,0 +1,60 @@
import QtQuick
import QtQuick.Controls
import FluentUI
Item {
property int number: 5
property int spacing: 4
property int size: 18
property int value:0
id:control
implicitWidth: container.width
implicitHeight: container.height
QtObject{
id:d
property int mouseValue: 0
property int itemSize: control.size+spacing*2
}
Row{
id:container
spacing: 0
Repeater{
model:control.number
Item{
width: d.itemSize
height: d.itemSize
FluIcon{
property bool isSelected : {
if(d.mouseValue!==0){
return index<d.mouseValue
}
return index<control.value
}
iconSize: control.size
iconSource: isSelected ? FluentIcons.FavoriteStarFill : FluentIcons.FavoriteStar
iconColor: isSelected ? FluTheme.primaryColor.dark : (FluTheme.dark ? "#FFFFFF" : "#000000")
anchors.centerIn: parent
}
}
}
}
MouseArea{
anchors.fill: container
hoverEnabled: true
onPositionChanged: (mouse)=>{
d.mouseValue = Number(mouse.x / d.itemSize)+1
}
onExited: {
d.mouseValue = 0
}
onClicked: (mouse)=>{
control.value = Number(mouse.x / d.itemSize)+1
}
}
}

View File

@ -1,4 +1,5 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.impl
import QtQuick.Templates as T

View File

@ -1,4 +1,5 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.impl
import QtQuick.Templates as T
@ -26,7 +27,6 @@ T.TextField {
y: control.topPadding
width: control.width - (control.leftPadding + control.rightPadding)
height: control.height - (control.topPadding + control.bottomPadding)
text: control.placeholderText
font: control.font
color: control.placeholderTextColor

View File

@ -99,39 +99,46 @@ Rectangle {
text:"AM/PM"
}
Popup{
Menu{
id:popup
width: 300
height: 340
width: container.width
height: container.height
modal: true
dim:false
enter: Transition {
reversible: true
NumberAnimation {
property: "opacity"
from:0
to:1
duration: 150
duration: 83
}
}
exit:Transition {
NumberAnimation {
property: "y"
from:0
to:popup.y
duration: 150
property: "opacity"
from:1
to:0
duration: 83
}
}
background:Item{}
contentItem: Rectangle{
background:Item{
FluShadow{
radius: 4
}
}
contentItem: Item{
clip: true
Rectangle{
id:container
anchors.fill: parent
height: 340
width: 300
radius: 4
color: FluTheme.dark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1)
MouseArea{
anchors.fill: parent
}
FluShadow{
radius: 4
}
RowLayout{
id:layout_content
spacing: 0
@ -333,9 +340,8 @@ Rectangle {
popup.close()
}
}
}
}
}
y:35
function showPopup() {
@ -373,12 +379,12 @@ Rectangle {
}
var pos = root.mapToItem(null, 0, 0)
if(window.height>pos.y+root.height+popup.height){
if(window.height>pos.y+root.height+container.height){
popup.y = root.height
} else if(pos.y>popup.height){
popup.y = -popup.height
} else if(pos.y>container.height){
popup.y = -container.height
} else {
popup.y = window.height-(pos.y+popup.height)
popup.y = window.height-(pos.y+container.height)
}
popup.open()
}

View File

@ -72,16 +72,32 @@ FluControl {
anchors.verticalCenter: parent.verticalCenter
color: selected ? "#FFFFFF" : "#666666"
Behavior on anchors.leftMargin {
NumberAnimation { duration: 150 }
NumberAnimation {
duration: 167
easing.type: Easing.Bezier
easing.bezierCurve: [ 1, 0, 0, 0 ]
}
}
Behavior on anchors.rightMargin {
NumberAnimation { duration: 150 }
NumberAnimation {
duration: 167
easing.type: Easing.Bezier
easing.bezierCurve: [ 1, 0, 0, 0 ]
}
}
Behavior on width {
NumberAnimation { duration: 150 }
NumberAnimation {
duration: 167
easing.type: Easing.Bezier
easing.bezierCurve: [ 1, 0, 0, 0 ]
}
}
Behavior on scale {
NumberAnimation { duration: 150 }
NumberAnimation {
duration: 167
easing.type: Easing.Bezier
easing.bezierCurve: [ 1, 0, 0, 0 ]
}
}
}
}

View File

@ -1,46 +1,33 @@
import QtQuick
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Layouts
import FluentUI
Item {
ApplicationWindow {
property string title: "FluentUI"
property int minimumWidth
property int maximumWidth
property int minimumHeight
property int maximumHeight
property int modality:0
signal initArgument(var argument)
property var pageRegister
default property alias content: container.data
property var window : {
if(Window.window == null)
return null
return Window.window
enum LaunchMode {
Standard,
SingleTask,
SingleInstance
}
property color color: {
if(window && window.active){
default property alias content: container.data
property bool closeDestory: true
property int launchMode: FluWindow.Standard
property string route
property var argument:({})
property var pageRegister
signal initArgument(var argument)
id:window
background: Rectangle{
color: {
if(active){
return FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(238/255,244/255,249/255,1)
}
return FluTheme.dark ? Qt.rgba(32/255,32/255,32/255,1) : Qt.rgba(243/255,243/255,243/255,1)
}
id:root
Behavior on opacity{
NumberAnimation{
duration: 100
}
}
Rectangle{
id:container
color:root.color
anchors.fill: parent
anchors.margins: (window && (window.visibility === Window.Maximized) && FluTheme.frameless) ? 8/Screen.devicePixelRatio : 0
clip: true
Behavior on color{
ColorAnimation {
duration: 300
@ -48,47 +35,43 @@ Item {
}
}
Rectangle{
border.width: 1
Item{
id:container
anchors.fill: parent
color: Qt.rgba(0,0,0,0,)
border.color:FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,230/255,234/255,1)
anchors.margins: window.visibility === Window.Maximized && FluTheme.frameless ? 8/Screen.devicePixelRatio : 0
clip: true
}
onActiveChanged: {
if(active){
helper.firstUpdate()
}
}
Connections{
target: FluApp
function onWindowReady(view){
if(FluApp.equalsWindow(view,window)){
helper.initWindow(view)
initArgument(helper.getArgument())
pageRegister = helper.getPageRegister()
helper.setTitle(title)
if(minimumWidth){
helper.setMinimumWidth(minimumWidth)
}
if(maximumWidth){
helper.setMaximumWidth(maximumWidth)
}
if(minimumHeight){
helper.setMinimumHeight(minimumHeight)
}
if(maximumHeight){
helper.setMaximumHeight(maximumHeight)
}
helper.setModality(root.modality);
helper.updateWindow()
onClosing:
(event)=>{
if(closeDestory){
destoryWindow()
}else{
visible = false
event.accepted = false
}
}
FluInfoBar{
id:infoBar
root: window
}
WindowHelper{
id:helper
}
FluInfoBar{
id:infoBar
root: root
Component.onCompleted: {
helper.initWindow(window)
initArgument(argument)
window.x = (Screen.width - window.width)/2
window.y = (Screen.desktopAvailableHeight - window.height)/2
}
function showSuccess(text,duration,moremsg){
@ -107,12 +90,12 @@ Item {
infoBar.showError(text,duration,moremsg);
}
function close(){
window.close()
function registerForPageResult(path){
return helper.createRegister(window,path)
}
function registerForPageResult(path){
return helper.createRegister(path)
function destoryWindow(){
helper.destoryWindow()
}
function onResult(data){

View File

@ -72,5 +72,6 @@
<file>controls/FluToggleButton.qml</file>
<file>controls/FluStatusView.qml</file>
<file>controls/FluPaneItemEmpty.qml</file>
<file>controls/FluRatingControl.qml</file>
</qresource>
</RCC>