Compare commits

...

23 Commits
1.1.0 ... 1.1.3

Author SHA1 Message Date
f20dc1edcb update 2023-03-23 18:05:42 +08:00
bfaffd3dab update 2023-03-23 17:52:08 +08:00
2c63eb21f0 update 2023-03-23 17:46:53 +08:00
f4e5316987 update 2023-03-23 17:40:10 +08:00
d3d6e64af1 update 2023-03-22 12:10:19 +08:00
82a7aa167a update 2023-03-22 11:54:19 +08:00
83f97159e9 update 2023-03-21 23:52:29 +08:00
5fcd95611f update 2023-03-21 18:19:46 +08:00
b83e70ba24 update 2023-03-20 21:28:12 +08:00
e29cb7433e update 2023-03-20 18:22:32 +08:00
9545175445 update 2023-03-18 22:52:24 +08:00
a447b260e7 update 2023-03-18 20:41:21 +08:00
8eb7e1df4a update 2023-03-18 20:20:59 +08:00
c622f80659 update 2023-03-18 01:25:49 +08:00
c0ed9cb41c update 2023-03-18 01:18:13 +08:00
e5a24ec642 update 2023-03-18 00:53:06 +08:00
6553584c3d update 2023-03-18 00:50:09 +08:00
1ea043ee13 update 2023-03-18 00:39:08 +08:00
0d6b0d9d25 update 2023-03-17 23:33:02 +08:00
5f71ad57d0 update 2023-03-17 23:03:46 +08:00
c789d53d6a update 2023-03-17 23:01:48 +08:00
f2bbbd5250 update 2023-03-17 22:59:21 +08:00
4e95923847 update 2023-03-17 17:56:50 +08:00
47 changed files with 1761 additions and 141 deletions

11
.gitignore vendored
View File

@ -1,14 +1,3 @@
# C++ objects and libs
*.slo
*.lo
*.o
*.a
*.la
*.lai
*.so
*.dll
*.dylib
# Qt-es
object_script.*.Release
object_script.*.Debug

View File

@ -7,16 +7,17 @@ ChatController::ChatController(QObject *parent)
networkManager = new QNetworkAccessManager(this);
}
void ChatController::sendMessage(const QString& text){
isLoading(true);
QUrl apiUrl("https://api.openai.com/v1/engines/text-davinci-003/completions");
QUrl apiUrl("https://api.openai.com/v1/chat/completions");
QNetworkRequest request(apiUrl);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Authorization", QString::fromStdString("Bearer %1").arg(QString::fromUtf8(QByteArray::fromBase64(baseKey.toUtf8()))).toUtf8());
QJsonObject requestData;
requestData.insert("prompt", text);
requestData.insert("max_tokens", 1000);
requestData.insert("temperature", 0.5);
requestData.insert("model", "gpt-3.5-turbo");
messages.append(createMessage("user",text));
requestData.insert("messages", messages);
QJsonDocument requestDoc(requestData);
QByteArray requestDataBytes = requestDoc.toJson();
QNetworkReply* reply = networkManager->post(request, requestDataBytes);
@ -26,11 +27,13 @@ void ChatController::sendMessage(const QString& text){
qDebug() << responseString;
QJsonDocument doc = QJsonDocument::fromJson(responseString.toUtf8());
QJsonObject jsonObj = doc.object();
QString text = jsonObj.value("choices").toArray().at(0).toObject().value("text").toString();
QString text = jsonObj.value("choices").toArray().at(0).toObject().value("message").toObject().value("content").toString();
if(text.isEmpty()){
text = "不好意思,我似乎听不懂您的意思";
text = "响应错误content为空数据";
}else{
messages.append(createMessage("assistant",text));
}
responseData(text);
responseData(text.trimmed());
} else {
responseData("网络错误:"+reply->errorString());
}
@ -38,3 +41,16 @@ void ChatController::sendMessage(const QString& text){
reply->deleteLater();
});
}
QJsonObject ChatController::createMessage(const QString& role,const QString& content){
QJsonObject message;
message.insert("role",role);
message.insert("content",content);
return message;
}
void ChatController::clipText(const QString& text){
qDebug()<<text;
QClipboard *clipboard = QGuiApplication::clipboard();
clipboard->setText(text);
}

View File

@ -7,7 +7,10 @@
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonArray>
#include <QGuiApplication>
#include <QClipboard>
#include <QByteArray>
#include <QFile>
#include "stdafx.h"
class ChatController : public QObject
@ -19,9 +22,13 @@ public:
explicit ChatController(QObject *parent = nullptr);
Q_INVOKABLE void sendMessage(const QString& text);
Q_INVOKABLE void clipText(const QString& text);
private:
QJsonObject createMessage(const QString& role,const QString& content);
private:
QNetworkAccessManager* networkManager;
QJsonArray messages;
QString baseKey = "c2stbXgxWm5MQkZ5TzhNYzNmRWl6eDZUM0JsYmtGSnNBWjNiakJjSXB6WGN3QW9KSk11";
};

101
example/T_Badge.qml Normal file
View File

@ -0,0 +1,101 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtGraphicalEffects 1.15
import FluentUI 1.0
FluScrollablePage{
title:"Badge"
FluArea{
width: parent.width
Layout.topMargin: 20
height: 106
paddings: 10
Column{
spacing: 15
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluText{
text:"一般出现在通知图标或头像的右上角,用于显示需要处理的消息条数"
}
Row{
spacing: 20
Rectangle{
width: 40
height: 40
radius: 8
color: Qt.rgba(191/255,191/255,191/255,1)
FluBadge{
count:0
}
}
Rectangle{
width: 40
height: 40
radius: 8
color: Qt.rgba(191/255,191/255,191/255,1)
FluBadge{
count:5
}
}
Rectangle{
width: 40
height: 40
radius: 8
color: Qt.rgba(191/255,191/255,191/255,1)
FluBadge{
count:50
}
}
Rectangle{
width: 40
height: 40
radius: 8
color: Qt.rgba(191/255,191/255,191/255,1)
FluBadge{
count:100
}
}
Rectangle{
width: 40
height: 40
radius: 8
color: Qt.rgba(191/255,191/255,191/255,1)
FluBadge{
isDot:true
}
}
Rectangle{
width: 40
height: 40
radius: 8
color: Qt.rgba(191/255,191/255,191/255,1)
FluBadge{
count:99
color: Qt.rgba(250/255,173/255,20/255,1)
}
}
Rectangle{
width: 40
height: 40
radius: 8
color: Qt.rgba(191/255,191/255,191/255,1)
FluBadge{
count:99
color: Qt.rgba(82/255,196/255,26/255,1)
}
}
}
}
}
}

View File

@ -14,6 +14,37 @@ FluScrollablePage{
text:"支持Tab键切换焦点空格键执行点击事件"
}
FluArea{
width: parent.width
height: 68
paddings: 10
FluTextButton{
disabled:text_button_switch.selected
text:"Text Button"
onClicked: {
showInfo("点击Text Button")
}
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
}
Row{
spacing: 5
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
}
FluToggleSwitch{
id:text_button_switch
Layout.alignment: Qt.AlignRight
text:"Disabled"
}
}
}
FluArea{
width: parent.width
height: 68
@ -40,8 +71,6 @@ FluScrollablePage{
FluToggleSwitch{
id:button_switch
Layout.alignment: Qt.AlignRight
}
FluText{
text:"Disabled"
}
}
@ -73,8 +102,6 @@ FluScrollablePage{
FluToggleSwitch{
id:filled_button_switch
Layout.alignment: Qt.AlignRight
}
FluText{
text:"Disabled"
}
}
@ -108,8 +135,6 @@ FluScrollablePage{
FluToggleSwitch{
id:icon_button_switch
Layout.alignment: Qt.AlignRight
}
FluText{
text:"Disabled"
}
}
@ -151,8 +176,6 @@ FluScrollablePage{
FluToggleSwitch{
id:drop_down_button_switch
Layout.alignment: Qt.AlignRight
}
FluText{
text:"Disabled"
}
}
@ -194,8 +217,6 @@ FluScrollablePage{
FluToggleSwitch{
id:radio_button_switch
Layout.alignment: Qt.AlignRight
}
FluText{
text:"Disabled"
}
}
@ -226,8 +247,6 @@ FluScrollablePage{
FluToggleSwitch{
id:check_box_switch
Layout.alignment: Qt.AlignRight
}
FluText{
text:"Disabled"
}
}

View File

@ -0,0 +1,35 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import FluentUI 1.0
FluScrollablePage{
title:"CalendarPicker"
FluArea{
width: parent.width
Layout.topMargin: 20
height: 350
paddings: 10
FluCalendarView{
}
}
FluArea{
width: parent.width
Layout.topMargin: 20
height: 80
paddings: 10
ColumnLayout{
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluCalendarPicker{
}
}
}
}

57
example/T_ColorPicker.qml Normal file
View File

@ -0,0 +1,57 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtGraphicalEffects 1.15
import FluentUI 1.0
FluScrollablePage{
title:"ColorPicker"
FluArea{
width: parent.width
height: 280
Layout.topMargin: 20
paddings: 10
ColumnLayout{
anchors{
verticalCenter: parent.verticalCenter
left:parent.left
}
FluText{
text:"此颜色组件是Github上大佬封装的"
}
FluTextButton{
leftPadding: 0
rightPadding: 0
text:"https://github.com/rshest/qml-colorpicker"
onClicked: {
Qt.openUrlExternally(text)
}
}
FluColorView{
}
}
}
FluArea{
width: parent.width
Layout.topMargin: 20
height: 60
paddings: 10
RowLayout{
FluText{
text:"点击选择颜色->"
Layout.alignment: Qt.AlignVCenter
}
FluColorPicker{
}
}
}
}

View File

@ -13,17 +13,26 @@ FluScrollablePage{
Layout.topMargin: 20
placeholderText: "单行输入框"
Layout.preferredWidth: 300
disabled:toggle_switch.selected
}
FluMultiLineTextBox{
Layout.topMargin: 20
Layout.preferredWidth: 300
placeholderText: "多行输入框"
disabled:toggle_switch.selected
}
FluAutoSuggestBox{
Layout.topMargin: 20
values:generateRandomNames(100)
placeholderText: "AutoSuggestBox"
Layout.preferredWidth: 300
disabled:toggle_switch.selected
}
FluToggleSwitch{
id:toggle_switch
text:"Disabled"
Layout.topMargin: 20
}
function generateRandomNames(numNames) {

View File

@ -12,4 +12,8 @@ FluScrollablePage{
FluToggleSwitch{
Layout.topMargin: 20
}
FluToggleSwitch{
Layout.topMargin: 20
text:"Disabled"
}
}

75
example/T_Tooltip.qml Normal file
View File

@ -0,0 +1,75 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import QtGraphicalEffects 1.15
import FluentUI 1.0
FluScrollablePage{
title:"Tooltip"
FluText{
Layout.topMargin: 20
text:"鼠标悬停不动弹出Tooltip"
}
FluArea{
width: parent.width
Layout.topMargin: 20
height: 68
paddings: 10
Column{
spacing: 5
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluText{
text:"FluIconButton的text属性自带Tooltip效果"
}
FluIconButton{
iconSource:FluentIcons.ChromeCloseContrast
iconSize: 15
text:"删除"
onClicked:{
showSuccess("点击IconButton")
}
}
}
}
FluArea{
width: parent.width
Layout.topMargin: 20
height: 68
paddings: 10
Column{
spacing: 5
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
}
FluText{
text:"给一个Button添加Tooltip效果"
}
FluButton{
id:button_1
text:"删除"
onClicked:{
showSuccess("点击一个Button")
}
FluTooltip{
visible: button_1.hovered
text:button_1.text
delay: 1000
}
}
}
}
}

View File

@ -26,5 +26,26 @@ CONFIG(debug,debug|release) {
DESTDIR = $$absolute_path($${_PRO_FILE_PWD_}/../bin/release)
}
win32 {
contains(QT_ARCH, i386) {
COPYDLL = $$absolute_path($${_PRO_FILE_PWD_}/../third/Win_x86/*.dll) $$DESTDIR
contains(QMAKE_CC, cl) {
QMAKE_PRE_LINK += $$QMAKE_COPY $$replace(COPYDLL, /, \\)
} else {
QMAKE_PRE_LINK += $$QMAKE_COPY $$COPYDLL
}
} else {
COPYDLL = $$absolute_path($${_PRO_FILE_PWD_}/../third/Win_x64/*.dll) $$DESTDIR
contains(QMAKE_CC, cl) {
QMAKE_PRE_LINK += $$QMAKE_COPY $$replace(COPYDLL, /, \\)
} else {
QMAKE_PRE_LINK += $$QMAKE_COPY $$COPYDLL
}
}
}
HEADERS += \
ChatController.h

View File

@ -1,4 +1,5 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import FluentUI 1.0
@ -34,7 +35,7 @@ FluWindow {
fontStyle: FluText.Title
}
FluText{
text:"v1.0.10"
text:"v1.1.3"
fontStyle: FluText.Body
Layout.alignment: Qt.AlignBottom
}
@ -69,7 +70,6 @@ FluWindow {
}
}
}
RowLayout{
spacing: 14
Layout.topMargin: 20
@ -78,22 +78,17 @@ FluWindow {
id:text_info
text:"如果该项目对你有作用就请点击上方链接给一个免费的star吧"
ColorAnimation {
id: animation
target: text_info
property: "color"
from: "red"
to: "blue"
duration: 1000
running: true
loops: Animation.Infinite
easing.type: Easing.InOutQuad
}
id: animation
target: text_info
property: "color"
from: "red"
to: "blue"
duration: 1000
running: true
loops: Animation.Infinite
easing.type: Easing.InOutQuad
}
}
}
}
}

View File

@ -3,6 +3,7 @@ import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import FluentUI 1.0
import Controller 1.0
import QtQuick.Dialogs 1.3
FluWindow {
@ -13,6 +14,11 @@ FluWindow {
title:"ChatGPT"
onInitArgument:
(argument)=>{
scrollview.focus = true
}
ChatController{
id:controller
@ -42,13 +48,13 @@ FluWindow {
Component{
id:com_text
TextEdit {
text: modelData.text
id:item_text
text: message
wrapMode: Text.WrapAnywhere
readOnly: true
textFormat: Text.RichText
selectByMouse: true
selectByKeyboard: true
selectedTextColor: color
selectedTextColor: Qt.rgba(51,153,255,1)
color:FluColors.Black
selectionColor: {
if(FluTheme.isDark){
@ -58,6 +64,12 @@ FluWindow {
}
}
width: Math.min(list_message.width-200,600,implicitWidth)
TapHandler{
acceptedButtons: Qt.RightButton
onTapped: {
menu_item.showMenu(item_text.selectedText)
}
}
}
}
@ -71,7 +83,6 @@ FluWindow {
margins: 10
}
color: FluTheme.isDark ? Qt.rgba(39/255,39/255,39/255,1) : Qt.rgba(245/255,245/255,245/255,1)
ListView{
id:list_message
anchors.fill: parent
@ -130,7 +141,7 @@ FluWindow {
Loader{
id:item_msg_loader
property var modelData: model
property var message: model.text
anchors.centerIn: parent
sourceComponent: com_text
}
@ -161,6 +172,7 @@ FluWindow {
ScrollView{
id:scrollview
anchors{
bottom: parent.bottom
left: parent.left
@ -172,6 +184,8 @@ FluWindow {
height: Math.min(textbox.implicitHeight,64)
FluMultiLineTextBox{
id:textbox
focus:true
placeholderText: "请输入消息"
}
}
@ -222,6 +236,23 @@ FluWindow {
}
}
FluMenu{
id:menu_item
focus: false
property string selectedText: ""
FluMenuItem{
text:"复制"
onClicked: {
controller.clipText(menu_item.selectedText)
showSuccess("复制成功")
}
}
function showMenu(text){
menu_item.selectedText = text
menu_item.popup()
}
}
function appendMessage(isMy,text){
model_message.append({isMy:isMy,text:text})
list_message.positionViewAtEnd()

View File

@ -72,6 +72,20 @@ FluWindow {
}
}
FluPaneItem{
title:"CalendarPicker"
onTap:{
nav_view.push("qrc:/T_CalendarPicker.qml")
}
}
FluPaneItem{
title:"ColorPicker"
onTap:{
nav_view.push("qrc:/T_ColorPicker.qml")
}
}
FluPaneItemHeader{
title:"Surface"
}
@ -90,6 +104,13 @@ FluWindow {
}
}
FluPaneItem{
title:"Badge"
onTap:{
nav_view.push("qrc:/T_Badge.qml")
}
}
FluPaneItem{
title:"Rectangle"
onTap:{
@ -97,7 +118,6 @@ FluWindow {
}
}
FluPaneItem{
title:"Carousel"
onTap:{
@ -123,6 +143,13 @@ FluWindow {
}
}
FluPaneItem{
title:"Tooltip"
onTap:{
nav_view.push("qrc:/T_Tooltip.qml")
}
}
FluPaneItem{
title:"Menu"
onTap:{

View File

@ -34,11 +34,15 @@
<file>T_DatePicker.qml</file>
<file>T_MultiWindow.qml</file>
<file>T_Menu.qml</file>
<file>T_Carousel.qml</file>
<file>res/image/banner_1.jpg</file>
<file>res/image/banner_2.jpg</file>
<file>res/image/banner_3.jpg</file>
<file>res/image/logo_openai.png</file>
<file>page/ChatPage.qml</file>
<file>T_Tooltip.qml</file>
<file>T_Badge.qml</file>
<file>T_CalendarPicker.qml</file>
<file>T_ColorPicker.qml</file>
<file>T_Carousel.qml</file>
</qresource>
</RCC>

View File

@ -17,7 +17,7 @@ function Main() {
New-Item -ItemType Directory $archiveName
# 拷贝exe
Copy-Item bin\release\$targetName $archiveName\
Copy-Item bin\release\* $archiveName\
# 拷贝依赖
windeployqt --qmldir . --plugindir $archiveName\plugins --no-translations --compiler-runtime $archiveName\$targetName
# 删除不必要的文件

View File

@ -27,7 +27,7 @@ function Main() {
New-Item -ItemType Directory $archiveName
# 拷贝exe
Copy-Item bin\release\$targetName $archiveName\
Copy-Item bin\release\* $archiveName\
# 拷贝依赖
windeployqt --qmldir . --plugindir $archiveName\plugins --no-translations --compiler-runtime $archiveName\$targetName
# 删除不必要的文件

View File

@ -35,6 +35,7 @@ void Fluent::registerTypes(const char *uri){
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluArea.qml"),uri,major,minor,"FluArea");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluBadge.qml"),uri,major,minor,"FluBadge");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluContentPage.qml"),uri,major,minor,"FluContentPage");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluScrollablePage.qml"),uri,major,minor,"FluScrollablePage");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluPaneItemHeader.qml"),uri,major,minor,"FluPaneItemHeader");
@ -42,10 +43,12 @@ void Fluent::registerTypes(const char *uri){
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluPaneItemSeparator.qml"),uri,major,minor,"FluPaneItemSeparator");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluNavigationView.qml"),uri,major,minor,"FluNavigationView");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluCalendarDatePicker.qml"),uri,major,minor,"FluCalendarDatePicker");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluCalenderView.qml"),uri,major,minor,"FluCalenderView");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluCalendarPicker.qml"),uri,major,minor,"FluCalendarPicker");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluCalendarView.qml"),uri,major,minor,"FluCalendarView");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluDatePicker.qml"),uri,major,minor,"FluDatePicker");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluTimePicker.qml"),uri,major,minor,"FluTimePicker");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluColorView.qml"),uri,major,minor,"FluColorView");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluColorPicker.qml"),uri,major,minor,"FluColorPicker");
qmlRegisterType(QUrl("qrc:/com.zhuzichu/controls/FluCarousel.qml"),uri,major,minor,"FluCarousel");

View File

@ -4,9 +4,6 @@
#include <QQuickView>
#include <QRegion>
//无边框窗口,主要用来实现自定义标题栏。
//Windows平台支持拖动和改变大小支持Aero效果
//非Windows平台去掉边框不做其它处理。由Qml模拟resize和拖动。
class FramelessViewPrivate;
class FramelessView : public QQuickView
{

View File

@ -0,0 +1,234 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import "content"
Rectangle {
id: colorPicker
property color colorValue: "transparent"
property bool enableAlphaChannel: true
property bool enableDetails: true
property int colorHandleRadius : 8
property color _changingColorValue : _hsla(hueSlider.value, sbPicker.saturation,sbPicker.brightness, alphaSlider.value)
on_ChangingColorValueChanged: {
colorValue = _changingColorValue
}
signal colorChanged(color changedColor)
implicitWidth: picker.implicitWidth
implicitHeight: picker.implicitHeight
color: "#00000000"
clip: true
RowLayout {
id: picker
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: colorHandleRadius
anchors.bottom: parent.bottom
spacing: 0
SBPicker {
id: sbPicker
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumWidth: 200
Layout.minimumHeight: 200
hueColor: {
var v = 1.0-hueSlider.value
if(0.0 <= v && v < 0.16) {
return Qt.rgba(1.0, 0.0, v/0.16, 1.0)
} else if(0.16 <= v && v < 0.33) {
return Qt.rgba(1.0 - (v-0.16)/0.17, 0.0, 1.0, 1.0)
} else if(0.33 <= v && v < 0.5) {
return Qt.rgba(0.0, ((v-0.33)/0.17), 1.0, 1.0)
} else if(0.5 <= v && v < 0.76) {
return Qt.rgba(0.0, 1.0, 1.0 - (v-0.5)/0.26, 1.0)
} else if(0.76 <= v && v < 0.85) {
return Qt.rgba((v-0.76)/0.09, 1.0, 0.0, 1.0)
} else if(0.85 <= v && v <= 1.0) {
return Qt.rgba(1.0, 1.0 - (v-0.85)/0.15, 0.0, 1.0)
} else {
return "red"
}
}
}
Item {
id: huePicker
width: 12
Layout.fillHeight: true
Layout.topMargin: colorHandleRadius
Layout.bottomMargin: colorHandleRadius
Rectangle {
anchors.fill: parent
id: colorBar
gradient: Gradient {
GradientStop { position: 1.0; color: "#FF0000" }
GradientStop { position: 0.85; color: "#FFFF00" }
GradientStop { position: 0.76; color: "#00FF00" }
GradientStop { position: 0.5; color: "#00FFFF" }
GradientStop { position: 0.33; color: "#0000FF" }
GradientStop { position: 0.16; color: "#FF00FF" }
GradientStop { position: 0.0; color: "#FF0000" }
}
}
ColorSlider {
id: hueSlider; anchors.fill: parent
}
}
Item {
id: alphaPicker
visible: enableAlphaChannel
width: 12
Layout.leftMargin: 4
Layout.fillHeight: true
Layout.topMargin: colorHandleRadius
Layout.bottomMargin: colorHandleRadius
Checkerboard { cellSide: 4 }
Rectangle {
anchors.fill: parent
gradient: Gradient {
GradientStop { position: 0.0; color: "#FF000000" }
GradientStop { position: 1.0; color: "#00000000" }
}
}
ColorSlider {
id: alphaSlider; anchors.fill: parent
}
}
Column {
id: detailColumn
Layout.leftMargin: 4
Layout.fillHeight: true
Layout.topMargin: colorHandleRadius
Layout.bottomMargin: colorHandleRadius
Layout.alignment: Qt.AlignRight
visible: enableDetails
PanelBorder {
width: parent.width
height: 30
visible: enableAlphaChannel
Checkerboard { cellSide: 5 }
Rectangle {
width: parent.width; height: 30
border.width: 1; border.color: "black"
color: colorPicker.colorValue
}
}
Item {
width: parent.width
height: 1
}
PanelBorder {
id: colorEditBox
height: 15; width: parent.width
TextInput {
anchors.fill: parent
color: "#AAAAAA"
selectionColor: "#FF7777AA"
font.pixelSize: 11
maximumLength: 9
focus: false
text: _fullColorString(colorPicker.colorValue, alphaSlider.value)
selectByMouse: true
}
}
Item {
width: parent.width
height: 8
}
Column {
width: parent.width
spacing: 1
NumberBox { caption: "H:"; value: hueSlider.value.toFixed(2) }
NumberBox { caption: "S:"; value: sbPicker.saturation.toFixed(2) }
NumberBox { caption: "B:"; value: sbPicker.brightness.toFixed(2) }
}
Item {
width: parent.width
height: 8
}
Column {
width: parent.width
spacing: 1
NumberBox {
caption: "R:"
value: _getChannelStr(colorPicker.colorValue, 0)
min: 0; max: 255
}
NumberBox {
caption: "G:"
value: _getChannelStr(colorPicker.colorValue, 1)
min: 0; max: 255
}
NumberBox {
caption: "B:"
value: _getChannelStr(colorPicker.colorValue, 2)
min: 0; max: 255
}
}
Item{
width: parent.width
height: 1
}
NumberBox {
visible: enableAlphaChannel
caption: "A:"; value: Math.ceil(alphaSlider.value*255)
min: 0; max: 255
}
}
}
function _hsla(h, s, b, a) {
var lightness = (2 - s)*b
var satHSL = s*b/((lightness <= 1) ? lightness : 2 - lightness)
lightness /= 2
var c = Qt.hsla(h, satHSL, lightness, a)
colorChanged(c)
return c
}
function _rgb(rgb, a) {
var c = Qt.rgba(rgb.r, rgb.g, rgb.b, a)
colorChanged(c)
return c
}
function _fullColorString(clr, a) {
return "#" + ((Math.ceil(a*255) + 256).toString(16).substr(1, 2) + clr.toString().substr(1, 6)).toUpperCase()
}
function _getChannelStr(clr, channelIdx) {
return parseInt(clr.toString().substr(channelIdx*2 + 1, 2), 16)
}
function setColor(color) {
var c = Qt.tint(color, "transparent")
alphaSlider.setValue(c.a)
colorPicker.colorValue = c
}
}

View File

@ -0,0 +1,16 @@
import QtQuick 2.15
Grid {
id: root
property int cellSide: 5
anchors.fill: parent
rows: height/cellSide; columns: width/cellSide
clip: true
Repeater {
model: root.columns*root.rows
Rectangle {
width: root.cellSide; height: root.cellSide
color: (index%2 == 0) ? "gray" : "white"
}
}
}

View File

@ -0,0 +1,43 @@
import QtQuick 2.15
Item {
property int cursorHeight: 7
property real value: (1 - pickerCursor.y/height)
width: 15
height: 300
Item {
id: pickerCursor
width: parent.width
Rectangle {
x: -3; y: -height*0.5
width: parent.width + 4; height: cursorHeight
border.color: "black"; border.width: 1
color: "transparent"
Rectangle {
anchors.fill: parent; anchors.margins: 2
border.color: "white"; border.width: 1
color: "transparent"
}
}
}
MouseArea {
y: -Math.round(cursorHeight/2)
height: parent.height+cursorHeight
anchors.left: parent.left
anchors.right: parent.right
function handleMouse(mouse) {
if (mouse.buttons & Qt.LeftButton) {
pickerCursor.y = Math.max(0, Math.min(height, mouse.y)-cursorHeight)
}
}
onPositionChanged: {
handleMouse(mouse)
}
onPressed: handleMouse(mouse)
}
function setValue(val) {
pickerCursor.y = height * (1 - val)
}
}

View File

@ -0,0 +1,39 @@
import QtQuick 2.15
Row {
property alias caption: captionBox.text
property alias value: inputBox.text
property alias min: numValidator.bottom
property alias max: numValidator.top
property alias decimals: numValidator.decimals
width: 80;
height: 15
spacing: 4
//anchors.margins: 2
Text {
id: captionBox
width: 18; height: parent.height
color: "#AAAAAA"
font.pixelSize: 11; font.bold: true
}
PanelBorder {
height: parent.height
TextInput {
id: inputBox
color: "#AAAAAA"; selectionColor: "#FF7777AA"
font.pixelSize: 11
maximumLength: 10
focus: false
readOnly: true
selectByMouse: true
validator: DoubleValidator {
id: numValidator
bottom: 0; top: 1; decimals: 2
notation: DoubleValidator.StandardNotation
}
}
}
}

View File

@ -0,0 +1,18 @@
import QtQuick 2.15
Rectangle {
width : 40; height : 15; radius: 2
border.width: 1; border.color: "#FF101010"
color: "transparent"
anchors.leftMargin: 1; anchors.topMargin: 3
clip: true
Rectangle {
anchors.fill: parent; radius: 2
anchors.leftMargin: -1; anchors.topMargin: -1
anchors.rightMargin: 0; anchors.bottomMargin: 0
border.width: 1; border.color: "#FF525255"
color: "transparent"
}
}

View File

@ -0,0 +1,69 @@
import QtQuick 2.15
Item {
id: root
property color hueColor : "blue"
property real saturation : pickerCursor.x/(width-2*r)
property real brightness : 1 - pickerCursor.y/(height-2*r)
property int r : colorHandleRadius
Rectangle {
x : r
y : r + parent.height - 2 * r
rotation: -90
transformOrigin: Item.TopLeft
width: parent.height - 2 * r
height: parent.width - 2 * r
gradient: Gradient {
GradientStop { position: 0.0; color: "#FFFFFF" }
GradientStop { position: 1.0; color: root.hueColor }
}
}
Rectangle {
x: r
y: r
width: parent.width - 2 * r
height: parent.height - 2 * r
gradient: Gradient {
GradientStop { position: 1.0; color: "#FF000000" }
GradientStop { position: 0.0; color: "#00000000" }
}
}
Item {
id: pickerCursor
Rectangle {
width: r*2; height: r*2
radius: r
border.color: "black"; border.width: 2
color: "transparent"
Rectangle {
anchors.fill: parent; anchors.margins: 2;
border.color: "white"; border.width: 2
radius: width/2
color: "transparent"
}
}
}
MouseArea {
anchors.fill: parent
x: r
y: r
function handleMouse(mouse) {
if (mouse.buttons & Qt.LeftButton) {
pickerCursor.x = Math.max(0,Math.min(mouse.x - r,width-2*r));
pickerCursor.y = Math.max(0,Math.min(mouse.y - r,height-2*r));
// pickerCursor.x = Math.max(-r,Math.min(mouse.x - r,width+r));
// pickerCursor.y = Math.max(-r,Math.min(mouse.y - r,height+r));
// pickerCursor.x = Math.max(0, Math.min(width, mouse.x) - 2 * r);
// pickerCursor.y = Math.max(0, Math.min(height, mouse.y) - 2 * r);
}
}
onPositionChanged: handleMouse(mouse)
onPressed: handleMouse(mouse)
}
}

View File

@ -8,11 +8,18 @@ TextField{
property int fontStyle: FluText.Body
property int pixelSize : FluTheme.textSize
property int iconSource: 0
property bool disabled: false
signal itemClicked(string data)
id:input
width: 300
color: FluTheme.isDark ? "#FFFFFF" : "#1A1A1A"
enabled: !disabled
color: {
if(disabled){
return FluTheme.isDark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1)
}
return FluTheme.isDark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1)
}
selectionColor: {
if(FluTheme.isDark){
return FluTheme.primaryColor.lighter
@ -22,6 +29,9 @@ TextField{
}
renderType: FluTheme.isNativeText ? Text.NativeRendering : Text.QtRendering
placeholderTextColor: {
if(disabled){
return FluTheme.isDark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1)
}
if(focus){
return FluTheme.isDark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1)
}

77
src/controls/FluBadge.qml Normal file
View File

@ -0,0 +1,77 @@
import QtQuick 2.15
Rectangle{
property bool isDot: false
property bool showZero: true
property int count: 0
id:control
color:Qt.rgba(255/255,77/255,79/255,1)
width: {
if(isDot)
return 10
if(count<10){
return 20
}else if(count<100){
return 30
}
return 40
}
height: {
if(isDot)
return 10
return 20
}
radius: {
if(isDot)
return 5
return 10
}
border.width: 1
border.color: Qt.rgba(1,1,1,1)
visible: {
if(showZero)
return true
return count!==0
}
anchors{
right: {
if(parent)
return parent.right
return undefined
}
top: {
if(parent)
return parent.top
return undefined
}
rightMargin: {
if(isDot){
return -2.5
}
return -(control.width/2)
}
topMargin: {
if(isDot){
return -2.5
}
return -10
}
}
Text{
anchors.centerIn: parent
color: Qt.rgba(1,1,1,1)
visible: !isDot
text:{
if(count<100)
return count
return count+"+"
}
}
}

View File

@ -1,5 +0,0 @@
import QtQuick 2.15
Item {
}

View File

@ -0,0 +1,92 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import FluentUI 1.0
Rectangle {
id:root
property color dividerColor: FluTheme.isDark ? Qt.rgba(77/255,77/255,77/255,1) : Qt.rgba(239/255,239/255,239/255,1)
property color hoverColor: FluTheme.isDark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1)
property color normalColor: FluTheme.isDark ? Qt.rgba(61/255,61/255,61/255,1) : Qt.rgba(254/255,254/255,254/255,1)
property var window : Window.window
color: {
if(mouse_area.containsMouse){
return hoverColor
}
return normalColor
}
height: 30
width: 120
radius: 4
border.width: 1
border.color: dividerColor
MouseArea{
id:mouse_area
hoverEnabled: true
anchors.fill: parent
onClicked: {
popup.showPopup()
}
}
FluText{
id:text_date
anchors{
left: parent.left
right: parent.right
rightMargin: 30
top: parent.top
bottom: parent.bottom
}
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text:"请选择日期"
}
FluIcon{
iconSource: FluentIcons.Calendar
iconSize: 14
color: text_date.color
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
rightMargin: 12
}
}
Popup{
id:popup
height: container.height
width: container.width
background: FluCalendarView{
id:container
onDateClicked:
(date)=>{
popup.close()
var year = date.getFullYear()
var month = date.getMonth()
var day = date.getDate()
text_date.text = year+"-"+(month+1)+"-"+day
}
}
contentItem: Item{}
function showPopup() {
var pos = root.mapToItem(null, 0, 0)
if(window.height>pos.y+root.height+popup.height){
popup.y = root.height
} else if(pos.y>popup.height){
popup.y = -popup.height
} else {
popup.y = window.height-(pos.y+popup.height)
}
popup.x = -(popup.width-root.width)/2
popup.open()
}
}
}

View File

@ -0,0 +1,476 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
Item {
id:control
property int displayMode: FluCalendarView.Month
property var date: new Date()
property var currentDate : new Date()
property var toDay: new Date()
signal dateClicked(var date)
width: 280
height: 325
enum DisplayMode {
Month,
Year,
Decade
}
Component.onCompleted: {
updateMouth(date)
}
function createItemWeek(name){
return {type:0,date:new Date(),name:name,isDecade:false}
}
function createItemDay(date){
return {type:1,date:date,name:"",isDecade:false}
}
function createItemMonth(date){
return {type:2,date:date,name:"",isDecade:false}
}
function createItemYear(date,isDecade){
return {type:3,date:date,name:"",isDecade:isDecade}
}
function updateDecade(date){
list_model.clear()
var year = date.getFullYear()
const decadeStart = Math.floor(year / 10) * 10;
for(var i = decadeStart ; i< decadeStart+10 ; i++){
list_model.append(createItemYear(new Date(i,0,1),true));
}
for(var j = decadeStart+10 ; j< decadeStart+16 ; j++){
list_model.append(createItemYear(new Date(j,0,1),false));
}
title.text = decadeStart+"-"+(decadeStart+10)
}
function updateYear(date){
list_model.clear()
var year = date.getFullYear()
for(var i = 0 ; i< 12 ; i++){
list_model.append(createItemMonth(new Date(year,i)));
}
for(var j = 0 ; j< 4 ; j++){
list_model.append(createItemMonth(new Date(year+1,j)));
}
title.text = year+"年"
}
function updateMouth(date){
list_model.clear()
list_model.append([createItemWeek("一"),createItemWeek("二"),createItemWeek("三"),createItemWeek("四"),createItemWeek("五"),createItemWeek("六"),createItemWeek("日")])
var year = date.getFullYear()
var month = date.getMonth()
var day = date.getDate()
var firstDayOfMonth = new Date(year, month, 1)
var dayOfWeek = firstDayOfMonth.getDay()
var headerSize = (dayOfWeek===0?7:dayOfWeek)-1
if(headerSize!==0){
var lastMonthYear = year;
var lastMonthMonth = month - 1
if (month === 0) {
lastMonthYear = year - 1
lastMonthMonth = 11
}
var lastMonthDays = new Date(lastMonthYear, lastMonthMonth+1, 0).getDate()
for (var i = headerSize-1; i >= 0; i--) {
list_model.append(createItemDay(new Date(lastMonthYear, lastMonthMonth,lastMonthDays-i)))
}
}
const lastDayOfMonth = new Date(year, month+1, 0).getDate()
for (let day = 1; day <= lastDayOfMonth; day++) {
list_model.append(createItemDay(new Date(year, month,day)))
}
var footerSize = 49-list_model.count
var nextMonthYear = year
var nextMonth = month + 1
if (month === 11) {
nextMonthYear = year + 1
nextMonth = 0
}
const nextDayOfMonth = new Date(nextMonthYear, nextMonth+1, 0).getDate()
for (let j = 1; j <= footerSize; j++) {
list_model.append(createItemDay(new Date(nextMonthYear, nextMonth,j)))
}
title.text = year+"年"+(month+1)+"月"
}
Component{
id:com_week
Item{
height: 40
width: 40
FluText{
text:name
anchors.centerIn: parent
}
}
}
Component{
id:com_year
Button{
id:item_control
property bool isYear: control.toDay.getFullYear() === date.getFullYear()
height: 70
width: 70
onClicked:{
control.date = date
displayMode = FluCalendarView.Year
updateYear(date)
}
background: Item{
Rectangle{
width: 60
height: 60
radius: 4
anchors.centerIn: parent
color:{
if(FluTheme.isDark){
if(item_control.hovered){
return Qt.rgba(1,1,1,0.05)
}
return Qt.rgba(0,0,0,0)
}else{
if(item_control.hovered){
return Qt.rgba(0,0,0,0.05)
}
return Qt.rgba(0,0,0,0)
}
}
}
Rectangle{
id:backgound_selected
anchors.centerIn: parent
width: 50
height: 50
radius: 25
visible: isYear
color: FluTheme.primaryColor.dark
}
FluText{
text:date.getFullYear()
anchors.centerIn: parent
color: {
if(isYear){
return "#FFFFFF"
}
if(isDecade){
return FluTheme.isDark ? "#FFFFFF" : "#1A1A1A"
}
return Qt.rgba(150/255,150/255,150/255,1)
}
}
}
contentItem: Item{}
}
}
Component{
id:com_month
Button{
id:item_control
property bool isYear: control.date.getFullYear() === date.getFullYear()
property bool isMonth: control.toDay.getFullYear() === date.getFullYear() && control.toDay.getMonth() === date.getMonth()
height: 70
width: 70
onClicked:{
control.date = date
displayMode = FluCalendarView.Month
updateMouth(date)
}
background: Item{
Rectangle{
width: 60
height: 60
radius: 4
anchors.centerIn: parent
color:{
if(FluTheme.isDark){
if(item_control.hovered){
return Qt.rgba(1,1,1,0.05)
}
return Qt.rgba(0,0,0,0)
}else{
if(item_control.hovered){
return Qt.rgba(0,0,0,0.05)
}
return Qt.rgba(0,0,0,0)
}
}
}
Rectangle{
id:backgound_selected
anchors.centerIn: parent
width: 50
height: 50
radius: 25
visible: isMonth
color: FluTheme.primaryColor.dark
}
FluText{
text:(date.getMonth()+1)+"月"
anchors.centerIn: parent
color: {
if(isMonth){
return "#FFFFFF"
}
if(isYear){
return FluTheme.isDark ? "#FFFFFF" : "#1A1A1A"
}
return Qt.rgba(150/255,150/255,150/255,1)
}
}
}
contentItem: Item{}
}
}
Component{
id:com_day
Button{
id:item_control
property bool isMonth: control.date.getMonth() === date.getMonth()
property bool isDay: control.currentDate.getFullYear() === date.getFullYear() && control.currentDate.getMonth() === date.getMonth() && control.currentDate.getDate() === date.getDate()
property bool isToDay: control.toDay.getFullYear() === date.getFullYear() && control.toDay.getMonth() === date.getMonth() && control.toDay.getDate() === date.getDate()
height: 40
width: 40
onClicked: {
currentDate = date
control.dateClicked(date)
}
background: Item{
Rectangle{
width: 36
height: 36
radius: 4
anchors.centerIn: parent
color:{
if(FluTheme.isDark){
if(item_control.hovered){
return Qt.rgba(1,1,1,0.05)
}
return Qt.rgba(0,0,0,0)
}else{
if(item_control.hovered){
return Qt.rgba(0,0,0,0.05)
}
return Qt.rgba(0,0,0,0)
}
}
}
Rectangle{
id:backgound_today
anchors.centerIn: parent
width: 36
height: 36
radius: 18
color:"#00000000"
visible: isDay
border.color: FluTheme.primaryColor.dark
border.width: 1
}
Rectangle{
id:backgound_selected
anchors.centerIn: parent
width: 30
height: 30
radius: 15
visible: isToDay
color: FluTheme.primaryColor.dark
}
FluText{
text:date.getDate()
anchors.centerIn: parent
color: {
if(isToDay){
return "#FFFFFF"
}
if(isMonth){
return FluTheme.isDark ? "#FFFFFF" : "#1A1A1A"
}
return Qt.rgba(150/255,150/255,150/255,1)
}
}
}
contentItem: Item{}
}
}
FluArea{
anchors.fill: parent
radius: 5
FluShadow{
radius: 5
}
Rectangle{
id:layout_divider
height: 1
width: parent.width
color: FluTheme.isDark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1)
anchors{
top: parent.top
topMargin: 44
}
}
Item{
id:layout_top
anchors{
left: parent.left
right: parent.right
top: parent.top
bottom: layout_divider.top
}
FluTextButton{
id:title
leftPadding: 0
rightPadding: 0
anchors{
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: 14
}
disabled: displayMode === FluCalendarView.Decade
onClicked:{
if(displayMode === FluCalendarView.Month){
displayMode = FluCalendarView.Year
updateYear(date)
}else if(displayMode === FluCalendarView.Year){
displayMode = FluCalendarView.Decade
updateDecade(date)
}
}
}
FluIconButton{
id:icon_up
iconSource: FluentIcons.CaretUpSolid8
iconSize: 10
anchors{
verticalCenter: parent.verticalCenter
right: icon_down.left
rightMargin: 14
}
onClicked: {
var year = date.getFullYear()
var month = date.getMonth()
if(displayMode === FluCalendarView.Month){
var lastMonthYear = year;
var lastMonthMonth = month - 1
if (month === 0) {
lastMonthYear = year - 1
lastMonthMonth = 11
}
date = new Date(lastMonthYear,lastMonthMonth,1)
updateMouth(date)
}else if(displayMode === FluCalendarView.Year){
date = new Date(year-1,month,1)
updateYear(date)
}else if(displayMode === FluCalendarView.Decade){
date = new Date(Math.floor(year / 10) * 10-10,month,1)
updateDecade(date)
}
}
}
FluIconButton{
id:icon_down
iconSource: FluentIcons.CaretDownSolid8
iconSize: 10
anchors{
verticalCenter: parent.verticalCenter
right: parent.right
rightMargin: 8
}
onClicked: {
var year = date.getFullYear()
var month = date.getMonth()
if(displayMode === FluCalendarView.Month){
var nextMonthYear = year
var nextMonth = month + 1
if (month === 11) {
nextMonthYear = year + 1
nextMonth = 0
}
date = new Date(nextMonthYear,nextMonth,1)
updateMouth(date)
}else if(displayMode === FluCalendarView.Year){
date = new Date(year+1,month,1)
updateYear(date)
}else if(displayMode === FluCalendarView.Decade){
date = new Date(Math.floor(year / 10) * 10+10,month,1)
updateDecade(date)
}
}
}
}
ListModel {
id:list_model
}
Item{
id:layout_bottom
anchors{
left: parent.left
right: parent.right
top: layout_divider.bottom
bottom: parent.bottom
}
GridView{
model: list_model
anchors.fill: parent
cellHeight: displayMode === FluCalendarView.Month ? 40 : 70
cellWidth: displayMode === FluCalendarView.Month ? 40 : 70
clip: true
boundsBehavior:Flickable.StopAtBounds
delegate: Loader{
property var modelData : model
property var name : model.name
property var date : model.date
property var isDecade: {
return model.isDecade
}
sourceComponent: {
if(model.type === 0){
return com_week
}
if(model.type === 1){
return com_day
}
if(model.type === 2){
return com_month
}
if(model.type === 3){
return com_year
}
return com_day
}
}
}
}
}
}

View File

@ -1,5 +0,0 @@
import QtQuick 2.15
Item {
}

View File

@ -0,0 +1,52 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQuick.Window 2.15
import FluentUI 1.0
Button{
id:control
width: 36
height: 36
implicitWidth: width
implicitHeight: height
background:
Rectangle{
id:layout_color
radius: 5
color: container.colorValue
border.color: {
if(hovered)
return FluTheme.primaryColor.light
return FluTheme.isDark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(226/255,229/255,234/255,1)
}
border.width: 1
}
contentItem: Item{}
onClicked: {
popup.showPopup()
}
Popup{
id:popup
height: container.height
width: container.width
background: FluColorView{
id:container
}
contentItem: Item{}
function showPopup() {
var pos = control.mapToItem(null, 0, 0)
if(window.height>pos.y+control.height+popup.height){
popup.y = control.height
} else if(pos.y>popup.height){
popup.y = -popup.height
} else {
popup.y = window.height-(pos.y+popup.height)
}
popup.x = -(popup.width-control.width)/2
popup.open()
}
}
}

View File

@ -0,0 +1,29 @@
import QtQuick 2.15
import "../colorpicker"
Item {
width: color_picker.width+10
height: color_picker.height
property alias colorValue: color_picker.colorValue
FluArea{
anchors.fill: parent
radius: 5
FluShadow{
radius: 5
}
ColorPicker{
id:color_picker
}
}
function setColor(color) {
color_picker.setColor(color)
}
}

View File

@ -98,7 +98,11 @@ Rectangle {
Popup{
id:popup
width: container.width
height: container.height
contentItem: Item{}
background: Rectangle{
id:container
width: 300
radius: 4
color: FluTheme.isDark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1)

View File

@ -6,10 +6,17 @@ TextArea{
property int fontStyle: FluText.Body
property int pixelSize : FluTheme.textSize
property bool disabled: false
id:input
width: 300
color: FluTheme.isDark ? "#FFFFFF" : "#1A1A1A"
color: {
if(disabled){
return FluTheme.isDark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1)
}
return FluTheme.isDark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1)
}
enabled: !disabled
wrapMode: Text.WrapAnywhere
renderType: FluTheme.isNativeText ? Text.NativeRendering : Text.QtRendering
selectByMouse: true
@ -24,6 +31,9 @@ TextArea{
inputItem: input
}
placeholderTextColor: {
if(disabled){
return FluTheme.isDark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1)
}
if(focus){
return FluTheme.isDark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1)
}

View File

@ -4,7 +4,7 @@ Item {
id:root
anchors.fill: parent
anchors.margins: -4
property color color: FluTheme.isDark ? "#FFFFFF" : "#000000"
property color color: FluTheme.isDark ? "#FFFFFF" : "#999999"
property int radius: 4

View File

@ -6,10 +6,17 @@ TextField{
property int fontStyle: FluText.Body
property int pixelSize : FluTheme.textSize
property bool disabled: false
id:input
width: 300
color: FluTheme.isDark ? "#FFFFFF" : "#1A1A1A"
enabled: !disabled
color: {
if(disabled){
return FluTheme.isDark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1)
}
return FluTheme.isDark ? Qt.rgba(255/255,255/255,255/255,1) : Qt.rgba(27/255,27/255,27/255,1)
}
renderType: FluTheme.isNativeText ? Text.NativeRendering : Text.QtRendering
selectionColor: {
if(FluTheme.isDark){
@ -19,6 +26,9 @@ TextField{
}
}
placeholderTextColor: {
if(disabled){
return FluTheme.isDark ? Qt.rgba(131/255,131/255,131/255,1) : Qt.rgba(160/255,160/255,160/255,1)
}
if(focus){
return FluTheme.isDark ? Qt.rgba(152/255,152/255,152/255,1) : Qt.rgba(141/255,141/255,141/255,1)
}

View File

@ -9,10 +9,13 @@ Rectangle{
radius: 4
layer.enabled: true
color: {
if(input.focus){
if(inputItem.disabled){
return FluTheme.isDark ? Qt.rgba(59/255,59/255,59/255,1) : Qt.rgba(252/255,252/255,252/255,1)
}
if(inputItem.focus){
return FluTheme.isDark ? Qt.rgba(36/255,36/255,36/255,1) : Qt.rgba(1,1,1,1)
}
if(input.hovered){
if(inputItem.hovered){
return FluTheme.isDark ? Qt.rgba(68/255,68/255,68/255,1) : Qt.rgba(251/255,251/255,251/255,1)
}
return FluTheme.isDark ? Qt.rgba(62/255,62/255,62/255,1) : Qt.rgba(1,1,1,1)
@ -25,16 +28,22 @@ Rectangle{
}
}
border.width: 1
border.color: FluTheme.isDark ? Qt.rgba(45/255,45/255,45/255,1) : Qt.rgba(238/255,238/255,238/255,1)
border.color: {
if(inputItem.disabled){
return FluTheme.isDark ? Qt.rgba(73/255,73/255,73/255,1) : Qt.rgba(237/255,237/255,237/255,1)
}
return FluTheme.isDark ? Qt.rgba(76/255,76/255,76/255,1) : Qt.rgba(240/255,240/255,240/255,1)
}
Rectangle{
width: parent.width
height: input.focus ? 3 : 1
height: inputItem.focus ? 3 : 1
anchors.bottom: parent.bottom
visible: !inputItem.disabled
color: {
if(FluTheme.isDark){
input.focus ? FluTheme.primaryColor.lighter : Qt.rgba(166/255,166/255,166/255,1)
inputItem.focus ? FluTheme.primaryColor.lighter : Qt.rgba(166/255,166/255,166/255,1)
}else{
return input.focus ? FluTheme.primaryColor.dark : Qt.rgba(183/255,183/255,183/255,1)
return inputItem.focus ? FluTheme.primaryColor.dark : Qt.rgba(183/255,183/255,183/255,1)
}
}
Behavior on height{

View File

@ -1,22 +1,44 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import FluentUI 1.0
FluText {
id:root
color: {
if(FluTheme.isDark){
return mouse_area.containsMouse?Qt.darker(FluTheme.primaryColor.lighter,1.1):FluTheme.primaryColor.lighter
Button {
property bool disabled: false
property color normalColor: FluTheme.isDark ? FluTheme.primaryColor.lighter : FluTheme.primaryColor.dark
property color hoverColor: FluTheme.isDark ? Qt.darker(normalColor,1.3) : Qt.lighter(normalColor,1.3)
property color disableColor: FluTheme.isDark ? Qt.rgba(82/255,82/255,82/255,1) : Qt.rgba(199/255,199/255,199/255,1)
property bool textBold: true
id: control
topPadding:5
bottomPadding:5
leftPadding:0
rightPadding:0
enabled: !disabled
focusPolicy:Qt.TabFocus
Keys.onSpacePressed: control.visualFocus&&clicked()
background: Item{
FluFocusRectangle{
visible: control.visualFocus
radius:8
}
return mouse_area.containsMouse?Qt.lighter(FluTheme.primaryColor.dark,1.1):FluTheme.primaryColor.dark
}
signal clicked
MouseArea{
id:mouse_area
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.clicked()
contentItem: FluText {
text: control.text
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.bold: control.textBold
color: {
color:{
if(disabled){
return disableColor
}
return hovered ? hoverColor :normalColor
}
}
}
}

View File

@ -105,7 +105,11 @@ Rectangle {
Popup{
id:popup
width: container.width
height: container.height
contentItem: Item{}
background: Rectangle{
id:container
width: 300
radius: 4
color: FluTheme.isDark ? Qt.rgba(51/255,48/255,48/255,1) : Qt.rgba(248/255,250/255,253/255,1)

View File

@ -1,6 +1,7 @@
import QtQuick 2.0
import QtQuick.Controls 2.0
import FluentUI 1.0
import QtQuick.Layouts 1.15
Button {
@ -8,10 +9,8 @@ Button {
property var clickFunc
id: control
width: 40
implicitWidth: 40
height: 20
implicitHeight: 20
implicitHeight: height
focusPolicy:Qt.TabFocus
Keys.onSpacePressed: control.visualFocus&&clicked()
onClicked: {
@ -21,50 +20,68 @@ Button {
}
selected = !selected
}
background : Rectangle {
width: control.width
height: control.height
radius: height / 2
FluFocusRectangle{
visible: control.visualFocus
radius: 20
}
color: {
if(FluTheme.isDark){
if(selected){
return FluTheme.primaryColor.dark
}
if(hovered){
return "#3E3E3C"
}
return "#323232"
}else{
if(selected){
return FluTheme.primaryColor.dark
}
if(hovered){
return "#F4F4F4"
}
return "#FFFFFF"
}
}
border.width: 1
border.color: selected ? Qt.lighter(FluTheme.primaryColor.dark,1.2) : "#666666"
contentItem: Item{}
background : RowLayout{
spacing: 0
Rectangle {
x: selected ? control.implicitWidth - width - 4 : 4
width: control.height - 8
height: control.height - 8
radius: width / 2
scale: hovered ? 1.2 : 1.0
anchors.verticalCenter: parent.verticalCenter
color: selected ? "#FFFFFF" : "#666666"
Behavior on x {
NumberAnimation { duration: 200 }
id:control_backgound
width: 40
height: control.height
radius: height / 2
smooth: true
antialiasing: true
FluFocusRectangle{
visible: control.visualFocus
radius: 20
}
Behavior on scale {
NumberAnimation { duration: 150 }
color: {
if(FluTheme.isDark){
if(selected){
return FluTheme.primaryColor.dark
}
if(hovered){
return "#3E3E3C"
}
return "#323232"
}else{
if(selected){
return FluTheme.primaryColor.dark
}
if(hovered){
return "#F4F4F4"
}
return "#FFFFFF"
}
}
border.width: 1
border.color: selected ? Qt.lighter(FluTheme.primaryColor.dark,1.2) : "#666666"
Rectangle {
x: selected ? control_backgound.width - width - 4 : 4
width: control.height - 8
height: control.height - 8
radius: width / 2
antialiasing: true
scale: hovered ? 1.2 : 1.0
smooth: true
anchors.verticalCenter: parent.verticalCenter
color: selected ? "#FFFFFF" : "#666666"
Behavior on x {
NumberAnimation { duration: 200 }
}
Behavior on scale {
NumberAnimation { duration: 150 }
}
}
}
FluText{
text: control.text
Layout.leftMargin: 5
visible: text !== ""
}
}
}

View File

@ -44,9 +44,18 @@
<file>controls/FluArea.qml</file>
<file>res/font/Segoe_Fluent_Icons.ttf</file>
<file>controls/FluDatePicker.qml</file>
<file>controls/FluCalenderView.qml</file>
<file>controls/FluCalendarDatePicker.qml</file>
<file>controls/FluCalendarView.qml</file>
<file>controls/FluCalendarPicker.qml</file>
<file>controls/FluFocusRectangle.qml</file>
<file>controls/FluCarousel.qml</file>
<file>controls/FluBadge.qml</file>
<file>controls/FluColorView.qml</file>
<file>controls/FluColorPicker.qml</file>
<file>colorpicker/ColorPicker.qml</file>
<file>colorpicker/content/Checkerboard.qml</file>
<file>colorpicker/content/ColorSlider.qml</file>
<file>colorpicker/content/NumberBox.qml</file>
<file>colorpicker/content/PanelBorder.qml</file>
<file>colorpicker/content/SBPicker.qml</file>
</qresource>
</RCC>

View File

@ -21,7 +21,7 @@ if %ANDROID% == YES copy /y %LIBFILE_PATH% %BUILDER_BIN_PATH%
if %1 == SHARED (
echo running install to qtqml folder
del /s /q %PRESET_PATH%\plugins.qmltypes
%QT_QML_FLUENT_PATH%\..\..\bin\qmlplugindump.exe -nonrelocatable FluentUI 1.0 .\ > %PRESET_PATH%\plugins.qmltypes
%QT_QML_FLUENT_PATH%\..\..\bin\qmlplugindump.exe -nonrelocatable FluentUI 1.0 > %PRESET_PATH%\plugins.qmltypes
rmdir /s /q %QT_QML_FLUENT_PATH% & md %QT_QML_FLUENT_PATH%
copy /y %BUILDER_BIN_PATH% %QT_QML_FLUENT_PATH%
xcopy %PRESET_PATH% %QT_QML_FLUENT_PATH% /s/e/i/y

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.