RibbonBackStageView: Added.

This commit is contained in:
Mentalflow 2024-05-16 15:09:51 +08:00
parent b11f82a6d6
commit 1df715bb3c
Signed by: Mentalflow
GPG Key ID: 5AE68D4401A2EE71
7 changed files with 698 additions and 49 deletions

View File

@ -81,7 +81,7 @@ qt_add_qml_module(${PROJECT_NAME}
URI ${PROJECT_NAME} URI ${PROJECT_NAME}
VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
RESOURCE_PREFIX "/qt/qml/" RESOURCE_PREFIX "/qt/qml/"
QML_FILES example.qml about.qml components/RibbonMessageListViewExample.qml QML_FILES example.qml about.qml components/RibbonMessageListViewExample.qml pages/SettingsMenuPage.qml
RESOURCES resources/imgs/heart.png resources/imgs/search.png RESOURCES resources/imgs/heart.png resources/imgs/search.png
) )

View File

@ -109,6 +109,10 @@ RibbonWindow {
} }
} }
onSettingsBtnClicked:{
backstagepopup.open()
}
RibbonTabPage{ RibbonTabPage{
id: basic_page id: basic_page
title: qsTr("Basic") title: qsTr("Basic")
@ -557,15 +561,6 @@ RibbonWindow {
text: "Test Text (Read Only)" text: "Test Text (Read Only)"
view_only: true view_only: true
} }
RibbonSwitchButton{
text: "Render"
grabber_text: RibbonTheme.nativeText ? "native" : "Qt"
checked: true
Layout.alignment: Qt.AlignHCenter
onClicked: {
RibbonTheme.nativeText = checked
}
}
} }
} }
} }
@ -633,45 +628,6 @@ RibbonWindow {
} }
} }
} }
RibbonTabGroup{
width: theme_layout.width + 30
text: qsTr("Theme")
RowLayout{
id: theme_layout
anchors.centerIn: parent
height: parent.height
spacing: 10
RibbonComboBox{
id: theme_combo
model: ListModel {
id: model_theme
ListElement { text: "Light" }
ListElement { text: "Dark" }
ListElement { text: "System" }
}
icon_source: RibbonIcons.DarkTheme
Component.onCompleted: update_state()
onActivated: {
if (currentText === "System")
RibbonTheme.theme_mode = RibbonThemeType.System
else if (currentText === "Light")
RibbonTheme.theme_mode = RibbonThemeType.Light
else
RibbonTheme.theme_mode = RibbonThemeType.Dark
}
Connections{
target: RibbonTheme
function onTheme_modeChanged(){
theme_combo.update_state()
}
}
function update_state(){
let str = (RibbonTheme.theme_mode === RibbonThemeType.System ? "System" : RibbonTheme.theme_mode === RibbonThemeType.Light ? "Light" : "Dark")
currentIndex = find(str)
}
}
}
}
} }
} }
@ -866,4 +822,34 @@ RibbonWindow {
enabled: false enabled: false
} }
} }
Component{
id: t_content
RibbonBackStagePage{
onPageNameChanged: t_text.text = pageName
Rectangle{
anchors.fill: parent
color: "transparent"
RibbonText{
id: t_text
anchors.centerIn: parent
font.pixelSize: 20
}
}
}
}
RibbonBackStageView{
id: backstagepopup
implicitHeight: root.height - root.borderWidth * 2
implicitWidth: root.width - root.borderWidth * 2
blurEnabled: true
blurTarget: root.window_items
radius: borderRadius
pageModel: [{"menu_text":"Home", "menu_icon":RibbonIcons.Home, "type":"head", "sourceComponent":t_content, "sourceArgs":{'pageName':"Home"}},
{"menu_text":"File", "menu_icon":RibbonIcons.Document, "type":"head", "sourceComponent":t_content, "sourceArgs":{'pageName':"File"}},
{"menu_text":"Search", "menu_icon":RibbonIcons.Search, "type":"body", "sourceComponent":t_content, "sourceArgs":{'pageName':"Search"}},
{"menu_text":"Account", "menu_icon":RibbonIcons.PersonAccounts, "type":"tail", "clickOnly":true, "clickFunc": ()=>console.log("Menu Account clicked")},
{"menu_text":"About", "menu_icon":RibbonIcons.Info, "type":"tail", "clickOnly":true, "clickFunc": ()=>root.show_window(Qt.resolvedUrl("about.qml"))},
{"menu_text":"Settings", "menu_icon":RibbonIcons.Settings, "type":"tail", "sourceUrl":Qt.resolvedUrl("pages/SettingsMenuPage.qml")}]
}
} }

View File

@ -0,0 +1,91 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import RibbonUI
RibbonBackStagePage{
id: page
pageName: qsTr("Settings")
ColumnLayout{
anchors{
top: parent.top
left: parent.left
right: parent.right
}
spacing: 100
RibbonBackStageGroup{
Layout.alignment: Qt.AlignTop
Layout.preferredHeight: theme_combo.height + 40
Layout.fillWidth: true
groupName: qsTr("Theme")
ColumnLayout{
RowLayout{
RibbonText{
text: qsTr("Current Theme: ")
}
RibbonComboBox{
id: theme_combo
model: ListModel {
id: model_theme
ListElement { text: "Light" }
ListElement { text: "Dark" }
ListElement { text: "System" }
}
icon_source: RibbonIcons.DarkTheme
Component.onCompleted: update_state()
onActivated: {
if (currentText === "System")
RibbonTheme.theme_mode = RibbonThemeType.System
else if (currentText === "Light")
RibbonTheme.theme_mode = RibbonThemeType.Light
else
RibbonTheme.theme_mode = RibbonThemeType.Dark
}
Connections{
target: RibbonTheme
function onTheme_modeChanged(){
theme_combo.update_state()
}
}
function update_state(){
let str = (RibbonTheme.theme_mode === RibbonThemeType.System ? "System" : RibbonTheme.theme_mode === RibbonThemeType.Light ? "Light" : "Dark")
currentIndex = find(str)
}
}
}
RowLayout{
RibbonText{
text: qsTr("Current Style: ")
}
RibbonSwitchButton{
text: qsTr("Style")
grabber_text: checked ? qsTr("Modern") : qsTr("Classic")
onClicked: RibbonTheme.modern_style = checked
checked: RibbonTheme.modern_style
}
}
}
}
RibbonBackStageGroup{
Layout.alignment: Qt.AlignTop
Layout.preferredHeight: render_btn.height + 40
Layout.fillWidth: true
groupName: qsTr("Text Render")
RowLayout{
RibbonText{
text: qsTr("Current Text Render: ")
}
RibbonSwitchButton{
id: render_btn
text: "Render"
grabber_text: RibbonTheme.nativeText ? "Native" : "Qt"
checked: true
Layout.alignment: Qt.AlignHCenter
onClicked: {
RibbonTheme.nativeText = checked
}
}
}
}
}
}

View File

@ -43,6 +43,7 @@ set(
qml/RibbonComboBox.qml qml/RibbonSpinBox.qml qml/RibbonScrollIndicator.qml qml/RibbonComboBox.qml qml/RibbonSpinBox.qml qml/RibbonScrollIndicator.qml
qml/RibbonScrollBar.qml qml/RibbonWindow.qml qml/RibbonMessage.qml qml/RibbonScrollBar.qml qml/RibbonWindow.qml qml/RibbonMessage.qml
qml/RibbonMessageListView.qml qml/RibbonTour.qml qml/RibbonTourContent.qml qml/RibbonMessageListView.qml qml/RibbonTour.qml qml/RibbonTourContent.qml
qml/RibbonBackStageView.qml qml/RibbonBackStagePage.qml qml/RibbonBackStageGroup.qml
) )
set ( set (

View File

@ -0,0 +1,48 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import RibbonUI
Item {
id: control
property string groupName: qsTr("Title")
property string bgColor: "transparent"
property int titleFontSize: 15
default property alias contentItem: container.data
property real bgRadius: 0
RibbonText{
id: title
anchors{
top: parent.top
left: parent.left
}
font.pixelSize: control.titleFontSize
font.bold: true
text: control.groupName
}
Rectangle{
id: border
anchors{
top: title.bottom
topMargin: 10
bottomMargin: anchors.topMargin
horizontalCenter: parent.horizontalCenter
}
height: 1
width: parent.width
color: RibbonTheme.dark_mode ? "#666666" : "#D1D1D1"
}
Rectangle{
id: container
color: control.bgColor
radius: control.bgRadius
anchors{
top: border.bottom
topMargin: border.anchors.bottomMargin
left: parent.left
right: parent.right
bottom: parent.bottom
}
}
}

View File

@ -0,0 +1,39 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import RibbonUI
Item {
id: control
property string pageName: qsTr("Name")
property string bgColor: "transparent"
property real bgRadius: 0
property int margins: 10
property int titleFontSize: 25
default property alias contentItem: container.data
RibbonText{
id: title
anchors{
top: parent.top
topMargin: margins
left: parent.left
leftMargin: margins
}
font.pixelSize: control.titleFontSize
text: control.pageName
}
Rectangle{
id: container
color: control.bgColor
radius: control.bgRadius
anchors{
top: title.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
margins: control.margins
}
}
}

View File

@ -0,0 +1,484 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import RibbonUI
Popup {
id: control
padding: 0
anchors.centerIn: Overlay.overlay
closePolicy: Popup.NoAutoClose
property bool blurEnabled: false
property var blurTarget: control
property bool showBackBtn: true
property string backText: qsTr("Back")
property int radius: 0
property var pageModel: []
signal backBtnClicked()
background: Item{}
exit: Transition {
NumberAnimation {
property: "opacity"
duration: 300
from:1
to:0
easing.type: Easing.OutSine
}
}
Component.onCompleted: refreshModel()
onPageModelChanged: refreshModel()
onAboutToShow: show()
onBackBtnClicked: hide()
RibbonBlur{
id: blur_bg
anchors.fill: parent
target: blurTarget
target_rect: Qt.rect(control.x + control.leftMargin, control.y + control.topMargin, control.width, control.height)
visible: blurEnabled
mask_color: content_bg.color
mask_opacity: 0
blur_radius: 0
radius: control.radius
Behavior on mask_opacity {
enabled: parent.visible
NumberAnimation {
duration: 300
easing.type: Easing.OutSine
}
}
Behavior on blur_radius {
enabled: parent.visible
NumberAnimation {
duration: 300
easing.type: Easing.OutSine
}
}
Behavior on opacity {
enabled: parent.visible
NumberAnimation {
duration: 300
easing.type: Easing.OutSine
}
}
}
RibbonRectangle{
id: menu_bg
anchors{
top: parent.top
bottom: parent.bottom
}
width: 150
x: -width
color: Qt.alpha(RibbonTheme.dark_mode ? "#363636" : RibbonTheme.modern_style ? "white" : "#365695", blurEnabled ? RibbonTheme.modern_style ? 0.8 : 0.9 : 1)
topLeftRadius: control.topMargin === 0 ? control.radius : 0
bottomLeftRadius: topLeftRadius
property int currentMenu: 0
RibbonButton{
id: back_btn
show_bg: false
show_hovered_bg: false
show_tooltip: false
text: backText
font.pixelSize: 30
icon_source: RibbonIcons.ArrowCircleLeft
implicitWidth: ribbon_icon.width
implicitHeight: ribbon_icon.height
text_color: RibbonTheme.modern_style && !RibbonTheme.dark_mode ? "black" : "white"
ribbon_icon.filled: hovered
anchors{
top: parent.top
topMargin: 30
left: parent.left
leftMargin: 30
}
visible: showBackBtn
ribbon_icon.icon_size: 30
ribbon_icon.color: {
if (RibbonTheme.modern_style && !RibbonTheme.dark_mode)
{
if(pressed)
return Qt.alpha("black", 0.8)
else
return "black"
}
else
{
if(pressed)
return Qt.alpha("white", 0.8)
else
return "white"
}
}
onClicked: backBtnClicked()
}
Component{
id: list_item
Rectangle{
id: item_bg
property int margins: 10
property var view: ListView.view
property bool clickOnly: typeof(model.clickOnly) !== 'undefined' ? model.clickOnly : false
property bool isCurrentMenu: {
if (item_bg.view.type === "head" && menu_bg.currentMenu === 0)
return true
else if (item_bg.view.type === "tail" && menu_bg.currentMenu === 2)
return true
else if (item_bg.view.type === "body" && menu_bg.currentMenu === 1)
return true
return false
}
width: view.width
height: item.height + margins * 2
color: {
if(RibbonTheme.modern_style)
return "transparent"
if(view.currentIndex === index && item_bg.isCurrentMenu)
{
if(mouse.containsMouse)
{
if(mouse.pressed)
return Qt.alpha(back_btn.text_color, 0.4)
return Qt.alpha(back_btn.text_color, 0.3)
}
else
return Qt.alpha(back_btn.text_color, 0.2)
}
else
{
if(mouse.containsMouse)
{
let color = back_btn.text_color === 'black' ? "white" : "black"
if(mouse.pressed)
return Qt.alpha(color, 0.3)
return Qt.alpha(color, 0.2)
}
else
return 'transparent'
}
}
Rectangle{
id: modern_border
anchors{
left: parent.left
leftMargin: 3
verticalCenter: parent.verticalCenter
}
radius: width / 2
color: {
if (mouse.containsMouse)
return RibbonTheme.dark_mode ? "#666666" : "#D1D1D1"
return "transparent"
}
width: 2
height: parent.height - 4
visible: RibbonTheme.modern_style
}
RowLayout{
id: item
anchors{
left: modern_border.visible ? modern_border.right : parent.left
leftMargin: (modern_border.visible ? -(modern_border.width + modern_border.anchors.leftMargin) : 0) + item_bg.margins * 2
right: parent.right
verticalCenter: parent.verticalCenter
}
RibbonIcon{
id :rib_icon
icon_source: typeof(model.menu_icon) === "number" ? model.menu_icon : 0
icon_source_filled: typeof(model.menu_icon_filled) === "number" ? model.menu_icon_filled : icon_source
icon_size: menu_label.contentHeight
visible: typeof(model.menu_icon) === "number" && model.menu_icon
Layout.alignment: Qt.AlignVCenter
filled: item_bg.view.currentIndex === index && item_bg.isCurrentMenu
color: model.menu_icon_color ? model.menu_icon_color : back_btn.text_color
}
Image {
id: pic_icon
source: typeof(model.menu_icon) === "string" ? model.menu_icon : ""
visible: typeof(model.menu_icon) === "string"
fillMode:Image.PreserveAspectFit
height: menu_label.contentHeight
width: height
Layout.alignment: Qt.AlignVCenter
}
Text{
id: menu_label
text: model.menu_text
color: !mouse.containsMouse && RibbonTheme.modern_style && item_bg.view.currentIndex === index && item_bg.isCurrentMenu ? RibbonTheme.dark_mode ? "#779CDB" : "#5882BB" : back_btn.text_color
Layout.alignment: Qt.AlignVCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: 13
elide: Text.ElideRight
font.family: Qt.platform.os === "osx" ? "PingFang SC" : "Microsoft YaHei UI"
renderType: RibbonTheme.nativeText ? Text.NativeRendering : Text.QtRendering
Layout.preferredWidth: {
let w = 0
w += rib_icon.visible ? rib_icon.contentWidth : 0
w += pic_icon.visible ? pic_icon.width : 0
w += (rib_icon.visible || pic_icon.visible) && menu_label.text ? item.spacing : 0
return item_bg.width - w - item_bg.margins * 4
}
Layout.leftMargin: (!model.menu_icon && model.menu_text) ? menu_label.contentHeight + item.spacing : 0
}
}
RibbonToolTip{
id: tooltip
visible: mouse.containsMouse && typeof(model.show_tooltip) != "undefined" ? model.show_tooltip : false
&& typeof(model.tool_text) != "undefined" ? model.tool_text : false
text: model.tool_text ? model.tool_text : ""
}
MouseArea{
id: mouse
anchors.fill: parent
hoverEnabled: true
onClicked: {
if (item_bg.clickOnly)
{
control.pageModel[model.globalIndex].clickFunc()
}
else{
if (item_bg.view.type === "head")
{
menu_bg.currentMenu = 0
ani_modern_border.targetMenu = head_menu_list
}
else if (item_bg.view.type === "tail")
{
menu_bg.currentMenu = 2
ani_modern_border.targetMenu = tail_menu_list
}
else
{
menu_bg.currentMenu = 1
ani_modern_border.targetMenu = body_menu_list
}
item_bg.view.currentIndex = index
content_view.currentIndex = model.globalIndex
}
}
}
}
}
ColumnLayout{
id: list_layout
anchors{
top: back_btn.bottom
topMargin: 10
left: parent.left
right: parent.right
bottom: parent.bottom
bottomMargin: anchors.topMargin * 3
}
ListView{
id: head_menu_list
model: ListModel{
}
delegate: list_item
Layout.alignment: Qt.AlignTop
Layout.preferredWidth: parent.width
Layout.preferredHeight: contentHeight
clip: true
interactive: false
property string type: "head"
}
Rectangle{
Layout.alignment: Qt.AlignHCenter
Layout.preferredHeight: 1
Layout.preferredWidth: parent.width - 40
color: RibbonTheme.modern_style ? RibbonTheme.dark_mode ? "#666666" : "#D1D1D1" :RibbonTheme.dark_mode ? "#B1B1B1" : Qt.alpha("white", 0.2)
visible: body_menu_list.count
}
ListView{
id: body_menu_list
model: ListModel{
}
delegate: list_item
Layout.preferredWidth: parent.width
Layout.preferredHeight: parent.height - head_menu_list.contentHeight - tail_menu_list.contentHeight
ScrollIndicator.vertical: RibbonScrollIndicator {
anchors.right: parent.right
anchors.rightMargin: 2
}
clip: true
property string type: "body"
}
Rectangle{
Layout.alignment: Qt.AlignHCenter
Layout.preferredHeight: 1
Layout.preferredWidth: parent.width - 40
color: RibbonTheme.modern_style ? RibbonTheme.dark_mode ? "#666666" : "#D1D1D1" :RibbonTheme.dark_mode ? "#B1B1B1" : Qt.alpha("white", 0.2)
visible: tail_menu_list.count
}
ListView{
id: tail_menu_list
model: ListModel{
}
delegate: list_item
Layout.alignment: Qt.AlignBottom
Layout.preferredWidth: parent.width
Layout.preferredHeight: contentHeight
clip: true
interactive: false
property string type: "tail"
}
}
Rectangle{
id: ani_modern_border
property int leftMargin: 3
property var targetMenu: head_menu_list
x: leftMargin
y: list_layout.y + targetMenu.y + (typeof(targetMenu.currentItem) !== 'undefined' && targetMenu.currentItem ? (targetMenu.currentItem.y + 2) : 0)
radius: width / 2
color: {
if(RibbonTheme.dark_mode)
return "#82ABF1"
else
return "#1651AA"
}
width: 2
height: (typeof(targetMenu.currentItem) !== 'undefined' && targetMenu.currentItem) ? targetMenu.currentItem.height - 4 : 0
visible: RibbonTheme.modern_style
Behavior on y {
NumberAnimation {
duration: 300
easing.type: Easing.OutQuart
}
}
}
Behavior on color {
ColorAnimation {
duration: 300
easing.type: Easing.OutSine
}
}
Behavior on x {
NumberAnimation {
duration: 300
easing.type: Easing.OutSine
}
}
}
RibbonRectangle{
id: content_bg
anchors{
top: parent.top
left: menu_bg.right
right: parent.right
bottom: parent.bottom
}
topRightRadius: control.topMargin === 0 ? control.radius : 0
bottomRightRadius: topRightRadius
color: Qt.alpha(RibbonTheme.dark_mode ? RibbonTheme.modern_style ? "#0A0A0A" : "#262626" : RibbonTheme.modern_style ? "#F0F0F0" : "white", 0)
Behavior on color {
ColorAnimation {
duration: 300
easing.type: Easing.OutSine
}
}
SwipeView{
id: content_view
interactive: false
anchors.fill: parent
spacing: 0
orientation: Qt.Vertical
Repeater{
model: control.pageModel
Loader {
active: SwipeView.isCurrentItem || SwipeView.isNextItem || SwipeView.isPreviousItem
source: typeof(modelData.sourceUrl) !== 'undefined' ? modelData.sourceUrl : ""
sourceComponent: typeof(control.pageModel[modelData.globalIndex].sourceComponent) !== 'undefined' && typeof(modelData.sourceUrl) === 'undefined' ? control.pageModel[modelData.globalIndex].sourceComponent : undefined
onLoaded: {
if (typeof(modelData.sourceArgs) === 'undefined')
return
else if(Object.keys(modelData.sourceArgs).length){
for (let arg in modelData.sourceArgs){
item[arg] = modelData.sourceArgs[arg]
}
}
else{
console.error("RibbonBackStageView: Arguments error, please check.")
}
}
}
}
}
}
Connections{
target: RibbonTheme
function onTheme_modeChanged(){
refresh()
}
}
function show(){
menu_bg.x = 0
content_bg.color = Qt.alpha(RibbonTheme.dark_mode ? RibbonTheme.modern_style ? "#0A0A0A" : "#262626" : RibbonTheme.modern_style ? "#F0F0F0" : "white", blurEnabled ? RibbonTheme.modern_style ? 0.95 : 0.9 : 1)
blur_bg.mask_opacity = blurEnabled ? 0.5 : 1
blur_bg.blur_radius = blurEnabled ? 32 : 0
blur_bg.opacity = 1
}
function hide(){
menu_bg.x = -menu_bg.width
content_bg.color = Qt.alpha(RibbonTheme.dark_mode ? RibbonTheme.modern_style ? "#0A0A0A" : "#262626" : RibbonTheme.modern_style ? "#F0F0F0" : "white", 0)
blur_bg.mask_opacity = 0
blur_bg.blur_radius = 0
blur_bg.opacity = 0
close()
}
function refresh(){
content_bg.color = Qt.alpha(RibbonTheme.dark_mode ? RibbonTheme.modern_style ? "#0A0A0A" : "#262626" : RibbonTheme.modern_style ? "#F0F0F0" : "white", blurEnabled ? RibbonTheme.modern_style ? 0.95 : 0.9 : 1)
blur_bg.mask_opacity = blurEnabled ? 0.5 : 1
blur_bg.blur_radius = blurEnabled ? 32 : 0
blur_bg.opacity = 1
}
function refreshModel(){
head_menu_list.model.clear()
body_menu_list.model.clear()
tail_menu_list.model.clear()
for (let i=0; i < pageModel.length; i++)
{
let item = pageModel[i]
item['globalIndex'] = i
if(pageModel[i].type === 'head')
{
head_menu_list.model.append(item)
}
else if(pageModel[i].type === 'tail')
{
tail_menu_list.model.append(item)
}
else
{
body_menu_list.model.append(item)
}
}
}
}