docs: 添加涉密文件自检工具实施计划
This commit is contained in:
105
UmiOCR-data/qt_res/qml/TabBar_/BarManager.qml
Normal file
105
UmiOCR-data/qt_res/qml/TabBar_/BarManager.qml
Normal file
@@ -0,0 +1,105 @@
|
||||
// ======================================================
|
||||
// =============== 标签栏的复制器的逻辑管理 ===============
|
||||
// ======================================================
|
||||
|
||||
/* 页面表现(布局、动画)应该在继承的子类中编写
|
||||
|
||||
|
||||
delegate: // 子类中填入按钮组件,属性必须包含:
|
||||
title: title_ // 标题
|
||||
checked: checked_ // 是否选中
|
||||
width: 宽
|
||||
height: 高
|
||||
*/
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
|
||||
Repeater {
|
||||
|
||||
// ========================= 【属性与变量】 =========================
|
||||
|
||||
model: ListModel{} // 标签元素列表,初始为空
|
||||
property bool isLock: false
|
||||
|
||||
|
||||
Component.onCompleted: {
|
||||
qmlapp.tab.bar = this // 逆向连接引用
|
||||
}
|
||||
// ========================= 【增删改查】 =========================
|
||||
|
||||
// 增: 在 index 处,插入一个标题为 title 的标签。
|
||||
function addTab(index, title){ // index=-1 代表尾部插入
|
||||
if(index<0) index=model.count // 尾部添加
|
||||
else if(index>model.count){
|
||||
console.error("【Error】添加标签失败:下标"+index+"超出范围"+model.count+"!")
|
||||
return
|
||||
}
|
||||
|
||||
model.insert(index, {
|
||||
"title_": title,
|
||||
"checked_": false
|
||||
})
|
||||
}
|
||||
|
||||
// 删: 在 index 处,删除该标签。
|
||||
function delTab(index){
|
||||
if(!isIndex(index, "【Error】删除标签失败:"))
|
||||
return
|
||||
model.remove(index) // 删除按钮
|
||||
}
|
||||
|
||||
// 改: 在 index 处,重设标签的 title 。
|
||||
function changeTab(index, title){
|
||||
if(!isIndex(index, "【Error】重命名标签失败:"))
|
||||
return
|
||||
model.set(index, {"title_": title})
|
||||
}
|
||||
|
||||
// 改: 选中 index 标签。
|
||||
function showTab(index){
|
||||
if(!isIndex(index, "【Error】选中标签失败:"))
|
||||
return
|
||||
for(let i=0; i<model.count; i++){
|
||||
itemAt(i).checked = (i==index)
|
||||
// model.set(index, {"checked_": (i==index)})
|
||||
}
|
||||
}
|
||||
|
||||
// 改: 将一个原本在 index 的标签移到 go 处。
|
||||
function moveTab(index, go){
|
||||
if(!isIndex(index, "【Error】移动标签失败:起点"))
|
||||
return
|
||||
if(!isIndex(go, "【Error】移动标签失败:终点"))
|
||||
return
|
||||
model.move(index, go, 1)
|
||||
}
|
||||
|
||||
// 改: 重置所有标签的序号
|
||||
function resetIndex() {
|
||||
for(let i=0, c=model.count; i<c; i++){
|
||||
itemAt(i).index = i
|
||||
}
|
||||
}
|
||||
|
||||
// 查: 返回下标 index 是否合法。
|
||||
function isIndex(index, msg=""){
|
||||
if(index<0 || index>=model.count){
|
||||
if(msg)
|
||||
console.error(msg+"下标"+index+"超出范围"+(model.count-1)+"!")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ========================= 【创建和删除事件】 =========================
|
||||
|
||||
// 创建新标签时
|
||||
onItemAdded: {
|
||||
resetIndex() // 重设序号
|
||||
}
|
||||
|
||||
onItemRemoved: {
|
||||
resetIndex() // 重设序号
|
||||
}
|
||||
}
|
||||
256
UmiOCR-data/qt_res/qml/TabBar_/HTabBar.qml
Normal file
256
UmiOCR-data/qt_res/qml/TabBar_/HTabBar.qml
Normal file
@@ -0,0 +1,256 @@
|
||||
// =========================================
|
||||
// =============== 水平标签栏 ===============
|
||||
// =========================================
|
||||
|
||||
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("锁定标签栏")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
171
UmiOCR-data/qt_res/qml/TabBar_/TabButton_.qml
Normal file
171
UmiOCR-data/qt_res/qml/TabBar_/TabButton_.qml
Normal file
@@ -0,0 +1,171 @@
|
||||
// ==================================================
|
||||
// =============== 水平标签栏的标签按钮 ===============
|
||||
// ==================================================
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtGraphicalEffects 1.15 // 阴影
|
||||
|
||||
import "../Widgets"
|
||||
|
||||
Button {
|
||||
id: btn
|
||||
|
||||
// 设定值
|
||||
property string title: "Unknown TabBtn" // 显示的标题
|
||||
property int index: -1 // 在标签栏中的序号
|
||||
|
||||
// 默认值
|
||||
height: size_.hTabBarHeight
|
||||
checkable: false // 手动控制
|
||||
z: checked? 10 : 0 // 选中模式下弹到顶层
|
||||
// 信号
|
||||
signal dragStart(int index) // 开始拖拽的信号
|
||||
signal dragFinish(int index) // 结束拖拽的信号
|
||||
signal dragMoving(int index, int x) // 拖拽移动的信号
|
||||
|
||||
// 按钮前景
|
||||
contentItem: Item {
|
||||
anchors.fill: parent
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
// TODO: 图标
|
||||
Item {
|
||||
width: size_.line*0.2 // 先占位
|
||||
height: btn.height // 适应整个按钮的高度
|
||||
}
|
||||
|
||||
// 标题
|
||||
Text_ {
|
||||
text: title // 外部传入的title
|
||||
|
||||
elide: Text.ElideRight // 隐藏超出宽度
|
||||
Layout.fillWidth: true // 填充宽度
|
||||
height: btn.height // 适应整个按钮的高度
|
||||
color: (btn.hovered || btn.checked)?theme.textColor:theme.subTextColor
|
||||
font.bold: btn.checked
|
||||
}
|
||||
|
||||
// 关闭按钮
|
||||
IconButton {
|
||||
// 未锁定,且主按钮悬停或选中时才显示
|
||||
visible: !qmlapp.tab.barIsLock && (btn.hovered || btn.checked)
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.rightMargin: size_.hTabBarHeight * 0.2
|
||||
|
||||
property real size: size_.hTabBarHeight * 0.7
|
||||
implicitWidth: size
|
||||
implicitHeight: size
|
||||
bgColor_: "#00000000"
|
||||
|
||||
icon_: "no"
|
||||
|
||||
onClicked: {
|
||||
qmlapp.tab.closeTabPage(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 按钮背景
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
|
||||
color: parent.checked ? theme.bgColor : (
|
||||
parent.hovered ? theme.coverColor1 : "#00000000"
|
||||
)
|
||||
|
||||
// 侧边小条
|
||||
Rectangle{
|
||||
visible: !parent.parent.checked
|
||||
height: size_.line
|
||||
width: 1
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
color: theme.coverColor4
|
||||
}
|
||||
|
||||
// 边缘阴影
|
||||
layer.enabled: parent.checked
|
||||
layer.effect: DropShadow {
|
||||
transparentBorder: true
|
||||
color: theme.coverColor3
|
||||
samples: size_.hTabBarHeight
|
||||
}
|
||||
|
||||
// 点击和拖拽处理
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton | Qt.MiddleButton
|
||||
|
||||
// 拖拽
|
||||
drag.target: qmlapp.tab.barIsLock ? undefined : parent.parent // 动态启用、禁用拖拽
|
||||
drag.axis: Drag.XAxis // 只能沿X轴
|
||||
drag.threshold: 50 // 起始阈值
|
||||
property bool dragActive: drag.active // 动态记录拖拽状态
|
||||
property int dragX: parent.parent.x // 动态记录拖拽时整体的位置
|
||||
|
||||
onPressed: { // 左键按下,切换焦点
|
||||
if(mouse.button === Qt.LeftButton) {
|
||||
qmlapp.tab.showTabPage(index)
|
||||
}
|
||||
}
|
||||
onClicked: { // 中键点击,删除标签
|
||||
if(mouse.button === Qt.MiddleButton && !qmlapp.tab.barIsLock) {
|
||||
qmlapp.tab.closeTabPage(index)
|
||||
}
|
||||
}
|
||||
onDragActiveChanged: {
|
||||
if(drag.active) { // 拖拽开始
|
||||
parent.opacity = 0.6
|
||||
parent.parent.y += parent.parent.height / 2
|
||||
dragStart(index)
|
||||
} else { // 拖拽结束
|
||||
parent.opacity = 1
|
||||
parent.parent.y -= parent.parent.height / 2
|
||||
dragFinish(index)
|
||||
}
|
||||
}
|
||||
onDragXChanged: {
|
||||
if(drag.active) {
|
||||
dragMoving(index, dragX)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 选中时的放大动画
|
||||
property bool enabledAni: false // true是允许动画
|
||||
property bool runAni: false
|
||||
Timer { // 计时器,保证初始化的一段时间内不允许动画
|
||||
running: true
|
||||
interval: 300
|
||||
onTriggered: enabledAni=true
|
||||
}
|
||||
onCheckedChanged: {
|
||||
if(enabledAni) runAni = checked
|
||||
}
|
||||
SequentialAnimation{ // 串行动画
|
||||
running: qmlapp.enabledEffect && runAni
|
||||
// 动画1:放大
|
||||
NumberAnimation{
|
||||
target: btn
|
||||
property: "scale"
|
||||
to: 1.2
|
||||
duration: 80
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
// 动画2:缩小
|
||||
NumberAnimation{
|
||||
target: btn
|
||||
property: "scale"
|
||||
to: 1
|
||||
duration: 150
|
||||
easing.type: Easing.InCubic
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user