277 lines
11 KiB
QML
277 lines
11 KiB
QML
// ==============================================
|
||
// =============== 任务进度控制面板 ===============
|
||
// ==============================================
|
||
|
||
import QtQuick 2.15
|
||
import QtQuick.Controls 2.15
|
||
|
||
Item {
|
||
id: missionCtrl
|
||
// 信号
|
||
signal runClicked // 点击 运行
|
||
signal pauseClicked // 点击 暂停
|
||
signal resumeClicked // 点击 恢复
|
||
signal stopClicked // 点击 停止
|
||
// 通知回调
|
||
function runFinished(allNum) { // 任务开始,传入总任务数
|
||
state_ = "run"
|
||
isWaiting = false
|
||
timer.start() // 新开始计时
|
||
msnNowNum = 0 // 刷新任务计数
|
||
msnAllNum = allNum
|
||
timer.updateNumber() // 刷新任务计数文本
|
||
}
|
||
function pauseFinished() { // 暂停
|
||
state_ = "pause"
|
||
isWaiting = false
|
||
timer.pause() // 暂停计时
|
||
timer.updateNumber() // 刷新任务计数文本
|
||
}
|
||
function resumeFinished() { // 恢复
|
||
state_ = "run"
|
||
isWaiting = false
|
||
timer.resume() // 恢复计时
|
||
timer.updateNumber() // 刷新任务计数文本
|
||
}
|
||
function stopFinished() { // 停止
|
||
state_ = "stop"
|
||
isWaiting = false
|
||
timer.pause() // 暂停计时
|
||
timer.updateNumber() // 刷新任务计数文本
|
||
}
|
||
function msnStep(step=1) { // 任务计数步进
|
||
msnNowNum += step
|
||
if(msnNowNum > msnAllNum) msnNowNum = msnAllNum
|
||
timer.updateNumber() // 刷新任务计数文本
|
||
}
|
||
|
||
// 任务状态
|
||
property string state_: "stop" // 当前状态, stop run pause
|
||
property bool isWaiting: false // 等待回调中
|
||
// 任务计数
|
||
property int msnAllNum: 0 // 总任务数
|
||
property int msnNowNum: 0 // 当前已完成任务数
|
||
clip: true
|
||
|
||
// 右:开始/暂停/停止按钮
|
||
Item {
|
||
id: ctrlRight
|
||
anchors.top: parent.top
|
||
anchors.bottom: parent.bottom
|
||
anchors.right: parent.right
|
||
// 右栏宽度
|
||
property real width_: size_.line * 8
|
||
width: width_
|
||
|
||
// 开始/暂停/恢复 按钮
|
||
Item {
|
||
id: btn1
|
||
anchors.top: parent.top
|
||
anchors.bottom: parent.bottom
|
||
anchors.left: parent.left
|
||
width: qmlapp.enabledEffect?ctrlRight.width_:(
|
||
state_==="stop"?ctrlRight.width_:ctrlRight.width_*0.5)
|
||
|
||
Button_ {
|
||
visible: state_ === "stop" && !isWaiting
|
||
anchors.fill: parent
|
||
bold_: true
|
||
bgColor_: theme.coverColor1
|
||
bgHoverColor_: theme.coverColor2
|
||
text_: qsTr("开始任务")
|
||
onClicked: {
|
||
if(isWaiting) return
|
||
isWaiting = true
|
||
Qt.callLater(runClicked)
|
||
}
|
||
}
|
||
IconButton {
|
||
visible: state_ !== "stop" || isWaiting
|
||
anchors.fill: parent
|
||
color: theme.textColor
|
||
bgColor_: theme.coverColor1
|
||
bgHoverColor_: theme.coverColor2
|
||
margins: size_.spacing
|
||
icon_: isWaiting?"wait":(state_==="run" ? "pause" : "run")
|
||
toolTip: (state_==="run" ? qsTr("暂停任务\n暂停后可以待机或休眠。\n但是关机或退出软件,将会丢弃任务内容。") :
|
||
qsTr("继续任务"))
|
||
onClicked: {
|
||
if(isWaiting) return
|
||
isWaiting = true
|
||
switch(state_) {
|
||
case "run": Qt.callLater(pauseClicked); return;
|
||
case "pause": Qt.callLater(resumeClicked); return;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 动画
|
||
PropertyAnimation on width { // 折叠一半
|
||
running: qmlapp.enabledEffect && state_!=="stop"
|
||
to: ctrlRight.width_*0.5
|
||
duration: 80
|
||
easing.type: Easing.InCubic
|
||
}
|
||
PropertyAnimation on width { // 展开全部
|
||
running: qmlapp.enabledEffect && state_==="stop"
|
||
to: ctrlRight.width_
|
||
duration: 80
|
||
easing.type: Easing.OutCubic
|
||
}
|
||
}
|
||
// 停止 按钮
|
||
IconButton {
|
||
id: btn2
|
||
anchors.top: parent.top
|
||
anchors.bottom: parent.bottom
|
||
anchors.right: parent.right
|
||
anchors.left: btn1.right
|
||
anchors.leftMargin: size_.smallSpacing
|
||
visible: width > 1
|
||
color: theme.noColor
|
||
bgColor_: theme.coverColor1
|
||
bgHoverColor_: theme.coverColor2
|
||
margins: size_.spacing
|
||
icon_: isWaiting?"wait":"stop"
|
||
toolTip: qsTr("终止任务\n放弃未完成的内容。")
|
||
onClicked: {
|
||
if(isWaiting) return
|
||
isWaiting = true
|
||
Qt.callLater(stopClicked)
|
||
}
|
||
}
|
||
}
|
||
// 左:文字/进度条
|
||
Item {
|
||
id: ctrlLeft
|
||
anchors.top: parent.top
|
||
anchors.bottom: parent.bottom
|
||
anchors.left: parent.left
|
||
anchors.right: ctrlRight.left
|
||
anchors.rightMargin: size_.spacing
|
||
Item {
|
||
id: ctrlLeftTop
|
||
anchors.top: parent.top
|
||
anchors.left: parent.left
|
||
anchors.right: parent.right
|
||
height: size_.line
|
||
|
||
Row {
|
||
anchors.top: parent.top
|
||
anchors.bottom: parent.bottom
|
||
anchors.right: parent.right
|
||
spacing: size_.line
|
||
|
||
// 计时器、任务计数器
|
||
Text_ {
|
||
id: timer
|
||
text: `${strState} ${strTime} ${strNumber}`
|
||
color: timer_.running?theme.textColor:(missionCtrl.msnNowNum<missionCtrl.msnAllNum?theme.noColor:theme.yesColor)
|
||
font.pixelSize: size_.smallText
|
||
verticalAlignment: Text.AlignVCenter // 垂直居中
|
||
property string strState: "" // 状态文本, "已暂停"
|
||
property string strTime: "" // 时间文本
|
||
property string strNumber: "" // 任务数量文本, 23/100
|
||
// 新开始计时
|
||
function start() {
|
||
timer_.running = true
|
||
startStamp = getTimestamp()
|
||
runTime = pauseTime = 0
|
||
updateTime()
|
||
}
|
||
// 暂停
|
||
function pause() {
|
||
timer_.running = false
|
||
pauseStartStamp = getTimestamp()
|
||
updateTime()
|
||
}
|
||
// 恢复计时
|
||
function resume() {
|
||
timer_.running = true
|
||
const t = getTimestamp()
|
||
pauseTime += t-pauseStartStamp // 累加暂停时长
|
||
updateTime()
|
||
}
|
||
// 获取时间戳
|
||
function getTimestamp() {
|
||
return (new Date()).getTime() / 1000
|
||
}
|
||
// 刷新时间
|
||
function updateTime() {
|
||
if(runTime < 0.1) {
|
||
strTime = "" // 时间太短,不显示
|
||
return
|
||
}
|
||
let s = ""
|
||
let minutes = Math.floor(runTime / 60)
|
||
let seconds = Math.floor(runTime % 60)
|
||
if(minutes < 10) minutes = "0"+minutes
|
||
if(seconds < 10) seconds = "0"+seconds
|
||
strTime = minutes + ':' + seconds
|
||
}
|
||
// 刷新数量、显示文本
|
||
function updateNumber() {
|
||
// n="23/100" , p="已停止"
|
||
let n = `${missionCtrl.msnNowNum}/${missionCtrl.msnAllNum}`
|
||
let p = ""
|
||
// 运行中
|
||
if(missionCtrl.state_ === "run") {
|
||
if(missionCtrl.msnNowNum < missionCtrl.msnAllNum)
|
||
p = qsTr("正在运行")
|
||
else
|
||
p = qsTr("正在保存") // 所有任务处理完毕,但任务队列未返回结束
|
||
}
|
||
// 暂停中
|
||
else if(missionCtrl.state_ === "pause") {
|
||
p = qsTr("已暂停")
|
||
}
|
||
// 已停止
|
||
else if(missionCtrl.state_ === "stop") {
|
||
if(missionCtrl.msnNowNum <= 0)
|
||
n = p = ""
|
||
else if(missionCtrl.msnNowNum < missionCtrl.msnAllNum)
|
||
p = qsTr("任务停止")
|
||
else
|
||
p = qsTr("任务完成")
|
||
}
|
||
// 刷新
|
||
timer.strNumber = n
|
||
timer.strState = p
|
||
if(missionCtrl.msnAllNum > 0)
|
||
missionProgress.percent = missionCtrl.msnNowNum/missionCtrl.msnAllNum
|
||
}
|
||
|
||
property real startStamp // 开始时间戳,秒
|
||
property real pauseStartStamp // 本次暂停开始的时间戳,秒
|
||
property real pauseTime // 暂停时长,秒
|
||
property real runTime // 运行时长,秒
|
||
property bool isPause: false // 是否正在暂停
|
||
Timer {
|
||
id: timer_
|
||
interval: 100 // 更新间隔
|
||
repeat: true
|
||
running: false
|
||
onTriggered: {
|
||
// 刷新运行时长
|
||
const timestamp = timer.getTimestamp()
|
||
timer.runTime = timestamp-timer.startStamp-timer.pauseTime
|
||
timer.updateTime()
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
HProgressBar {
|
||
id: missionProgress
|
||
anchors.bottom: parent.bottom
|
||
anchors.left: parent.left
|
||
anchors.right: parent.right
|
||
anchors.bottomMargin: size_.line * 0.1
|
||
height: size_.line * 0.5
|
||
highlightColor: missionCtrl.state_==="run"?theme.yesColor:theme.coverColor4
|
||
color: theme.bgColor
|
||
percent: 0
|
||
}
|
||
}
|
||
} |