Files
work-secretfile-selfcheck/UmiOCR-data/qt_res/qml/TabPages/BatchDOC/BatchDOC.qml

312 lines
10 KiB
QML
Raw Normal View History

// ==================================================
// =============== 功能页:批量文档处理 ===============
// ==================================================
import QtQuick 2.15
import QtQuick.Controls 2.15
import ".."
import "../../Widgets"
import "../../Widgets/ResultLayout"
import "../../Widgets/IgnoreArea"
/*
path
pages
state
page_count
range_start
range_end
is_encrypted
is_authenticate
password
*/
TabPage {
id: tabPage
// ========================= 【逻辑】 =========================
property string msnID: "" // 当前任务ID
// 异步加载一批文档路径
function addDocs(paths) {
if(paths.length <= 0) return
const isRecurrence = configsComp.getValue("mission.recurrence")
qmlapp.asynFilesLoader.run(paths,"doc",isRecurrence,onAddDocs)
}
// 完毕后,将合法表格加入表格
function onAddDocs(docs) {
if(docs.length <= 0) return
let encryptedCount = 0
for(let i in docs) {
const info = docs[i]
filesTableView.add({
// 显示:路径,状态,页范围
path: info.path,
pages: `${info.page_count}`, // 如果范围为整本,只显示总页数。否则显示 起始-结束
state: info.is_encrypted ? qsTr("加密") : "" ,
// 数据
page_count: info.page_count,
range_start: 1,
range_end: info.page_count,
is_encrypted: info.is_encrypted, // 有密码
is_authenticate: !info.is_encrypted, // 已解密(密码正确)
password: "",
})
if(info.is_encrypted) encryptedCount++
}
if(encryptedCount > 0) {
qmlapp.popup.simple(qsTr("%1个加密文档").arg(encryptedCount),
qsTr("请点击文件名填写密码"))
}
}
// 运行文档任务
function docStart() {
const fileCount = filesTableView.rowCount
if(fileCount <= 0) {
ctrlPanel.stopFinished()
return
}
// 获取信息
const docs = filesTableView.getColumnsValues([
"path","range_start", "range_end", "page_count", "is_encrypted", "is_authenticate", "password"])
// 第1次遍历检查密码填写
for(let i = 0; i < fileCount; i++) {
const d = docs[i]
if(d.is_encrypted && !d.is_authenticate) {
qmlapp.popup.message(qsTr("文档已加密"), qsTr("【%1】\n请点击文档名设置密码").arg(d.path), "warning")
ctrlPanel.stopFinished()
return
}
}
// 第2次遍历刷新信息
let allPages = 0 // 页总数
for(let i = 0; i < fileCount; i++) {
const d = docs[i]
allPages += d.range_end - d.range_start + 1
filesTableView.setProperty(d.path, "state", qsTr("排队"))
}
// 若tabPanel面板的下标没有变化过则切换到记录页
if(tabPanel.indexChangeNum < 2)
tabPanel.currentIndex = 1
// 任务进度 开始计时
ctrlPanel.runFinished(allPages)
// 提交任务
const argd = configsComp.getValueDict()
tabPage.callPy("msnDocs", docs, argd)
}
// 停止文档任务
function docStop() {
tabPage.callPy("msnStop")
// 刷新表格,清空未执行的任务的状态
let msnLength = filesTableView.rowCount
for(let i = 0; i < msnLength; i++) {
const row = filesTableView.get(i)
const s = row.state
if(s.length > 0 && s[0] !== "√" && s[0] !== "×") {
filesTableView.setProperty(i, "state", "")
}
}
ctrlPanel.stopFinished()
}
// 文件表格中单击文档
function onClickDoc(index) {
if(ctrlPanel.state_ !== "stop") return
const info = filesTableView.get(index)
if(Object.keys(info).length > 0)
previewDoc.show(info)
}
// 关闭页面
function closePage() {
if(ctrlPanel.state_ !== "stop") {
const argd = { yesText: qsTr("依然关闭") }
const callback = (flag)=>{
if(flag) {
docStop()
delPage()
}
}
qmlapp.popup.dialog("", qsTr("任务正在进行中。\n要结束任务并关闭页面吗"), callback, "warning", argd)
}
else {
delPage()
}
}
// ========================= 【python调用qml】 =========================
// 准备开始处理一个文档
function onDocStart(path) {
// 刷新表格显示
const d = filesTableView.get(path)
let state = `0/${d.range_end - d.range_start + 1}`
filesTableView.setProperty(path, "state", state)
}
// 获取一个文档的一页的结果
function onDocGet(path, page, res) {
// 刷新单个文档的信息
const d = filesTableView.get(path)
const state = `${page - d.range_start + 1}/${d.range_end - d.range_start + 1}`
filesTableView.setProperty(path, "state", state)
// 提取文字,添加到结果表格
const title = path2name(path)
res.title = `${title} - ${page}`
resultsTableView.addOcrResult(res)
ctrlPanel.msnStep(1)
}
// 一个文档处理完毕。 isAll==true 时所有文档处理完毕。
function onDocEnd(path, msg, isAll) {
const errTitle = qsTr("文档识别异常")
// 成功结束
if(msg.startsWith("[Success]")) {
filesTableView.setProperty(path, "state", "√")
msg = ""
}
// 单个文档任务失败,总体未结束
else if(!isAll) {
filesTableView.setProperty(path, "state", "× "+ qsTr("失败"))
qmlapp.popup.simple(errTitle, msg)
}
// 所有文档处理完毕
if(isAll) {
const simpleType = configsComp.getValue("other.simpleNotificationType")
qmlapp.popup.simple(qsTr("批量识别完成"), "", simpleType)
if(msg) // 如果有异常,则弹窗
qmlapp.popup.message(errTitle, msg, "error")
ctrlPanel.stopFinished()
// 任务完成后续操作
qmlapp.globalConfigs.utilsDicts.postTaskHardwareCtrl(
configsComp.getValue("postTaskActions.system")
)
}
}
// 路径转文件名
function path2name(path) {
const parts = path.split("/")
return parts[parts.length - 1]
}
// ========================= 【布局】 =========================
// 配置
configsComp: BatchDOCConfigs {}
// 主区域:可切换双栏面板
DoubleSwitchableLayout {
id: doubleLayout
saveKey: "BatchDOC_1"
anchors.fill: parent
// 面板A控制板+文件表格
itemA: Panel {
anchors.fill: parent
// 上方控制板
MissionCtrlPanel {
id: ctrlPanel
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: size_.spacing
height: size_.line * 2
onRunClicked: tabPage.docStart()
onPauseClicked: {
tabPage.callPy("msnPause")
pauseFinished()
}
onResumeClicked: {
tabPage.callPy("msnResume")
resumeFinished()
}
onStopClicked: tabPage.docStop()
}
// 下方文件表格
FilesTableView {
id: filesTableView
anchors.top: ctrlPanel.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: size_.spacing
anchors.topMargin: size_.smallSpacing
headers: [
{key: "path", title: qsTr("文档"), left: true, display: path2name,
btn: true, onClicked:onClickDoc},
{key: "state", title: qsTr("状态"), btn: true, onClicked:onClickDoc},
{key: "pages", title: qsTr("页数"), btn: true, onClicked:onClickDoc},
]
openBtnText: qsTr("打开文档")
clearBtnText: qsTr("清空")
defaultTips: qsTr("拖入文档或文件夹")
fileDialogTitle: qsTr("请选择文档")
fileDialogNameFilters: [qsTr("文档")+" (*.pdf *.xps *.epub *.mobi *.fb2 *.cbz)"]
isLock: ctrlPanel.state_ !== "stop"
onAddPaths: {
tabPage.addDocs(paths)
}
}
}
// 面板B文字输出 & 设置
itemB: Panel {
anchors.fill: parent
// 配置项控制板
TabPanel {
id: tabPanel
anchors.fill: parent
anchors.margins: size_.spacing
isMenuTop: doubleLayout.isRow // 左右布局时,菜单在顶部;上下布局时菜单在底部
menuHeight: size_.line * 2
// 结果面板
ResultsTableView {
id: resultsTableView
anchors.fill: parent
visible: false
}
tabsModel: [
{
"key": "configs",
"title": qsTr("设置"),
"component": configsComp.panelComponent,
},
{
"key": "ocrResult",
"title": qsTr("记录"),
"component": resultsTableView,
},
]
}
}
}
// 鼠标拖入文档
DropArea_ {
id: "addDocsDropArea"
anchors.fill: parent
callback: tabPage.addDocs
}
// 预览面板
PreviewDoc {
id: previewDoc
anchors.fill: parent
configsComp: tabPage.configsComp
updateInfo: (path, info) => {
let infoA = filesTableView.get(path)
Object.assign(infoA, info)
filesTableView.set(path, infoA)
}
}
}