256 lines
9.1 KiB
QML
256 lines
9.1 KiB
QML
|
|
// =========================================
|
|||
|
|
// =============== 水平标签栏 ===============
|
|||
|
|
// =========================================
|
|||
|
|
|
|||
|
|
import QtQuick 2.15
|
|||
|
|
import QtQuick.Controls 2.15
|
|||
|
|
import QtQuick.Layouts 1.15
|
|||
|
|
|
|||
|
|
import "../Widgets"
|
|||
|
|
|
|||
|
|
RowLayout {
|
|||
|
|
id: hTabBarLayout
|
|||
|
|
anchors.fill: parent
|
|||
|
|
spacing: 0
|
|||
|
|
|
|||
|
|
// 标签栏控制(左,置顶按钮)
|
|||
|
|
Item {
|
|||
|
|
width: size_.hTabBarHeight
|
|||
|
|
Layout.fillHeight: true
|
|||
|
|
// 图钉按钮
|
|||
|
|
Button {
|
|||
|
|
checkable: true
|
|||
|
|
checked: mainWindowRoot.isMainWindowTop
|
|||
|
|
onCheckedChanged: { // 双向绑定锁定标记
|
|||
|
|
mainWindowRoot.isMainWindowTop = checked
|
|||
|
|
qmlapp.globalConfigs.setValue("window.isMainWindowTop", checked, true)
|
|||
|
|
}
|
|||
|
|
anchors.fill: parent
|
|||
|
|
anchors.margins: 4
|
|||
|
|
|
|||
|
|
contentItem: Icon_ {
|
|||
|
|
icon: "pin"
|
|||
|
|
anchors.fill: parent
|
|||
|
|
color: parent.checked ? theme.bgColor : theme.textColor
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
background: Rectangle {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
radius: size_.btnRadius
|
|||
|
|
color: parent.checked ? theme.coverColor4 : (
|
|||
|
|
parent.hovered ? theme.coverColor2 : "#00000000"
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ToolTip_ {
|
|||
|
|
visible: parent.hovered
|
|||
|
|
text: qsTr("窗口置顶")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 标签栏本体(中)
|
|||
|
|
Rectangle {
|
|||
|
|
id: hTabBarMain
|
|||
|
|
Layout.fillWidth: true
|
|||
|
|
Layout.fillHeight: true
|
|||
|
|
color: "#00000000"
|
|||
|
|
|
|||
|
|
property int tabWidth: 200 // 标签当前宽度
|
|||
|
|
|
|||
|
|
// 方法:重设标签按钮宽度
|
|||
|
|
function resetTabBtnWidth() {
|
|||
|
|
let w = hTabBarMain.width
|
|||
|
|
if(!qmlapp.tab.barIsLock) w -= tabBarControl.width // 无锁定时,减去+按钮宽度
|
|||
|
|
w = w / barManager.model.count
|
|||
|
|
tabWidth = Math.min(w, size_.line * 8)
|
|||
|
|
}
|
|||
|
|
onWidthChanged: resetTabBtnWidth() // 监听标签栏总宽度变化
|
|||
|
|
// 监听改变锁定,重设宽度
|
|||
|
|
property bool isLock: qmlapp.tab.barIsLock
|
|||
|
|
onIsLockChanged: {
|
|||
|
|
hTabBarMain.resetTabBtnWidth()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
MouseArea { // 点击标签栏空余位置,都是添加新标签
|
|||
|
|
anchors.fill: parent
|
|||
|
|
onClicked: {
|
|||
|
|
if(!qmlapp.tab.barIsLock)
|
|||
|
|
qmlapp.tab.addNavi() // 添加导航页
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Rectangle { // 标签按钮下方的阴影
|
|||
|
|
// anchors.bottom: parent.bottom
|
|||
|
|
// width: parent.width
|
|||
|
|
// height: size_.hTabBarHeight * 0.5
|
|||
|
|
// gradient: Gradient {
|
|||
|
|
// GradientStop { position: 0.0; color: "#00000000" }
|
|||
|
|
// GradientStop { position: 1.0; color: theme.coverColor2 }
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
Rectangle { // 拖拽时的位置指示器
|
|||
|
|
id: dragIndicator
|
|||
|
|
visible: false
|
|||
|
|
width: parent.tabWidth
|
|||
|
|
height: size_.hTabBarHeight
|
|||
|
|
gradient: Gradient { // 水平渐变
|
|||
|
|
orientation: Gradient.Horizontal
|
|||
|
|
GradientStop { position: 1.0; color: "#00000000" }
|
|||
|
|
GradientStop { position: 0.0; color: theme.coverColor3 }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 水平标签栏行布局
|
|||
|
|
Row {
|
|||
|
|
id: hTabBarMainRow
|
|||
|
|
spacing: -1 // 给负的间隔,是为了让选中标签能覆盖左右两边标签的竖线
|
|||
|
|
|
|||
|
|
// ===== 标签按钮组 =====
|
|||
|
|
BarManager {
|
|||
|
|
id: barManager
|
|||
|
|
// 标签元素模板
|
|||
|
|
delegate: TabButton_ {
|
|||
|
|
title: title_ // 标题
|
|||
|
|
checked: checked_ // 初始时是否选中
|
|||
|
|
index: index_ // 初始位置
|
|||
|
|
width: hTabBarMain.tabWidth
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 事件:创建新标签时(与父类的槽同时生效)
|
|||
|
|
onItemAdded: {
|
|||
|
|
// 链接表现相关的槽函数
|
|||
|
|
item.dragStart.connect(dragStart)
|
|||
|
|
item.dragFinish.connect(dragFinish)
|
|||
|
|
item.dragMoving.connect(dragMoving)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 事件:按钮数量变化
|
|||
|
|
onCountChanged: hTabBarMain.resetTabBtnWidth()
|
|||
|
|
|
|||
|
|
// ========================= 【拖拽相关】 =========================
|
|||
|
|
|
|||
|
|
property var intervalList: [] // 记录按钮位置区间的列表
|
|||
|
|
property var originalPosList: [] // 记录按钮初始位置的列表
|
|||
|
|
property int originalX // 记录本轮拖拽前,被拖拽按钮原本的位置
|
|||
|
|
function dragStart(index){ // 方法:开始拖拽
|
|||
|
|
// 重新记录当前所有按钮的位置
|
|||
|
|
originalX = itemAt(index).x
|
|||
|
|
intervalList = [-Infinity] // 下限:负无穷
|
|||
|
|
originalPosList = [itemAt(0).x]
|
|||
|
|
for(let i=1, c=model.count; i < c; i++){ // 按钮位置区间
|
|||
|
|
const it = itemAt(i)
|
|||
|
|
intervalList.push(it.x)
|
|||
|
|
originalPosList.push(it.x)
|
|||
|
|
}
|
|||
|
|
intervalList.push(Infinity) // 上限:负无穷
|
|||
|
|
dragIndicator.visible = true
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
function btnDragIndex(index){ // 函数:返回当前index应该所处的序号
|
|||
|
|
const dragItem = itemAt(index)
|
|||
|
|
const x = dragItem.x + Math.round(dragItem.width/2) // 被拖动按钮的中心位置
|
|||
|
|
let go = 0 // 应该拖放到的位置
|
|||
|
|
for(const c=intervalList.length-1; go < c; go++){
|
|||
|
|
if(x >= intervalList[go] && x <= intervalList[go+1]){
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return go;
|
|||
|
|
}
|
|||
|
|
function dragMoving(index, x){ // 方法:拖拽移动
|
|||
|
|
let go = btnDragIndex(index) // 应该拖放到的序号
|
|||
|
|
dragIndicator.x = originalPosList[go]
|
|||
|
|
}
|
|||
|
|
function dragFinish(index){ // 方法:结束拖拽
|
|||
|
|
dragIndicator.visible = false
|
|||
|
|
let go = btnDragIndex(index) // 应该拖放到的序号
|
|||
|
|
if(index !== go){ // 需要移动
|
|||
|
|
// model.move(index, go, 1)
|
|||
|
|
qmlapp.tab.moveTabPage(index, go)
|
|||
|
|
} else { // 无需移动,则回到原位
|
|||
|
|
itemAt(index).x = originalX
|
|||
|
|
}
|
|||
|
|
resetIndex()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 元素:控制按钮
|
|||
|
|
Rectangle{
|
|||
|
|
id: tabBarControl
|
|||
|
|
color: "#00000000"
|
|||
|
|
width: size_.hTabBarHeight
|
|||
|
|
height: size_.hTabBarHeight
|
|||
|
|
visible: !qmlapp.tab.barIsLock
|
|||
|
|
|
|||
|
|
// 添加“+”按钮
|
|||
|
|
IconButton {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
anchors.margins: 4
|
|||
|
|
icon_: "add"
|
|||
|
|
color: theme.textColor
|
|||
|
|
onClicked: {
|
|||
|
|
qmlapp.tab.addNavi() // 添加导航页
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 动画
|
|||
|
|
add: Transition { // 添加子项
|
|||
|
|
enabled: qmlapp.enabledEffect
|
|||
|
|
NumberAnimation {
|
|||
|
|
properties: "opacity, scale" // 透明度和大小从小到大
|
|||
|
|
from: 0; to: 1.0
|
|||
|
|
easing.type: Easing.OutBack // 缓动:超出反弹
|
|||
|
|
duration: 300
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
move: Transition { // 移动子项
|
|||
|
|
enabled: qmlapp.enabledEffect
|
|||
|
|
NumberAnimation {
|
|||
|
|
properties: "x,y"
|
|||
|
|
easing.type: Easing.OutBack
|
|||
|
|
duration: 300
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 标签栏控制(右,锁定按钮)
|
|||
|
|
Item{
|
|||
|
|
width: size_.hTabBarHeight
|
|||
|
|
Layout.fillHeight: true
|
|||
|
|
|
|||
|
|
// 锁定“🔒︎”按钮
|
|||
|
|
Button {
|
|||
|
|
checkable: true
|
|||
|
|
checked: qmlapp.tab.barIsLock
|
|||
|
|
onCheckedChanged: { // 双向绑定锁定标记
|
|||
|
|
qmlapp.tab.barIsLock = checked
|
|||
|
|
qmlapp.globalConfigs.setValue("window.barIsLock", checked, true)
|
|||
|
|
}
|
|||
|
|
anchors.fill: parent
|
|||
|
|
anchors.margins: 4
|
|||
|
|
|
|||
|
|
contentItem: Icon_ {
|
|||
|
|
icon: "lock"
|
|||
|
|
anchors.fill: parent
|
|||
|
|
color: parent.checked ? theme.bgColor : theme.textColor
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
background: Rectangle {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
radius: size_.btnRadius
|
|||
|
|
color: parent.checked ? theme.coverColor4 : (
|
|||
|
|
parent.hovered ? theme.coverColor2 : "#00000000"
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ToolTip_ {
|
|||
|
|
visible: parent.hovered
|
|||
|
|
text: qsTr("锁定标签栏")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|