232 lines
8.3 KiB
QML
232 lines
8.3 KiB
QML
// ===============================================
|
||
// =============== 页面的逻辑管理器 ===============
|
||
// ===============================================
|
||
|
||
|
||
import QtQuick 2.15
|
||
import TagPageConnector 1.0 // Python页面连接器
|
||
|
||
Item {
|
||
|
||
// ========================= 【列表】 =========================
|
||
|
||
property var infoList: [
|
||
{
|
||
key: "Navigation", // 页面的唯一标识符。同时也是对应Python模块的名称。
|
||
url: "", // 页面的qml文件路径。留空时,初始化为 key/key.qml
|
||
needController: false, // 为true时才需要加载对应Python模块,不需要可留空
|
||
title: qsTr("新标签页"), // 页面的显示名称。
|
||
intro: "" // 页面的简介。
|
||
},
|
||
{
|
||
key: "ScreenshotOCR",
|
||
needController: true,
|
||
title: qsTr("截图OCR"),
|
||
intro: qsTr("# 截图OCR\n\n屏幕截图,快捷转文字。也支持粘贴图片。")
|
||
},
|
||
{
|
||
key: "BatchOCR",
|
||
needController: true,
|
||
title: qsTr("批量OCR"),
|
||
intro: qsTr("# 批量OCR\n\n导入本地图片或文件夹,批量转换文字。\n\n支持格式:")
|
||
+ " `jpg, jpe, jpeg, jfif, png, webp, bmp, tif, tiff`",
|
||
},
|
||
{
|
||
key: "BatchDOC",
|
||
needController: true,
|
||
title: qsTr("批量文档"),
|
||
intro: qsTr("# 批量文档识别\n\n批量导入文档,提取文字,或生成双层可搜索PDF。\n\n支持格式:")
|
||
+ " `pdf, xps, epub, mobi, fb2, cbz`",
|
||
},
|
||
{
|
||
key: "QRCode",
|
||
needController: true,
|
||
title: qsTr("二维码"),
|
||
intro: qsTr("# 二维码\n\n识别或生成二维码、条形码。\n\n支持协议:")
|
||
+ " `Aztec, Codabar, Code128, Code39, Code93, DataBar, DataBarExpanded, DataMatrix, EAN13, EAN8, ITF, LinearCodes, MatrixCodes, MaxiCode, MicroQRCode, PDF417, QRCode, UPCA, UPCE`",
|
||
},
|
||
{
|
||
key: "GlobalConfigsPage",
|
||
title: qsTr("全局设置"),
|
||
intro: qsTr("# 全局设置\n\n调节全局设置项,对所有页面生效。")
|
||
},
|
||
{
|
||
key: "About",
|
||
title: qsTr("关于"),
|
||
intro: qsTr("# 关于")
|
||
},
|
||
]
|
||
|
||
/* 存放当前已打开的页面
|
||
obj: 页面组件对象
|
||
info: 页面信息(infoList中对应项的引用)
|
||
infoIndex: 页面信息下标(infoList中对应项的引用)
|
||
*/
|
||
property var pageList: []
|
||
|
||
// Python的页面连接器,手动维护单例状态
|
||
TagPageConnector { id: connector }
|
||
|
||
// ========================= 【增删改查】 =========================
|
||
|
||
// 初始化
|
||
function initListUrl() {
|
||
for(let i=infoList.length-1; i>=0; i--){
|
||
const info = infoList[i]
|
||
if(!info.url) {
|
||
info.url = `${info.key}/${info.key}.qml`
|
||
}
|
||
}
|
||
}
|
||
|
||
// 创建一个页面的组件类 comp
|
||
function getComp(infoIndex) {
|
||
const info = infoList[infoIndex]
|
||
if(info.comp) return info.comp
|
||
const url = info.url
|
||
const comp = Qt.createComponent(url)
|
||
if (comp.status === Component.Ready) { // 加载成功
|
||
infoList[infoIndex].comp = comp
|
||
return comp
|
||
} else{ // 加载失败
|
||
if (comp.status === Component.Error) { // 加载失败,提取错误信息
|
||
let str = comp.errorString()
|
||
const last = str.lastIndexOf(":")
|
||
if(last < 0) last = -1
|
||
str = str.substring(last+1).replace("\n","")
|
||
console.error(`【Error】加载页面文件失败:【${url}】${str}`)
|
||
}
|
||
else{
|
||
console.error(`【Error】加载页面文件异常:【${url}】`)
|
||
}
|
||
return undefined
|
||
}
|
||
}
|
||
|
||
// 创建并返回一个 infoList[infoIndex] 页面。
|
||
function newPage(infoIndex){
|
||
const info = infoList[infoIndex]
|
||
// 实例化逻辑控制器
|
||
let ctrlKey = ""
|
||
if(info.needController){
|
||
ctrlKey = connector.addPage(info.key)
|
||
if(!ctrlKey){
|
||
console.error("【Error】添加页面失败:组件["+info.key+"]创建控制器失败!")
|
||
return undefined
|
||
}
|
||
}
|
||
else { // 新增一个不带控制器的简单页
|
||
ctrlKey = connector.addSimplePage(info.key)
|
||
}
|
||
// 检查组件
|
||
let comp = getComp(infoIndex)
|
||
if(!comp){
|
||
console.error("【Error】添加页面失败:组件["+info.key+"]的comp无法创建!")
|
||
return undefined
|
||
}
|
||
// 实例化页面,挂到巢下,写入自身参数
|
||
const obj = comp.createObject(pagesNest, {
|
||
z: -1, visible: false,
|
||
ctrlKey: ctrlKey, // Python控制器key
|
||
connector: connector, // Python控制器对象
|
||
})
|
||
// 收集并返回页面对象信息
|
||
const dic = {
|
||
obj: obj,
|
||
info: info,
|
||
infoIndex: infoIndex,
|
||
ctrlKey: ctrlKey
|
||
}
|
||
// 向控制器传入页面对象
|
||
connector.setPageQmlObj(ctrlKey, obj)
|
||
return dic
|
||
}
|
||
|
||
// 增: 在 pageList 的 index 处,插入一个 infoList[infoIndex] 页面。
|
||
function addPage(index, infoIndex){ // index=-1 代表尾部插入
|
||
// 列表添加
|
||
const dic = newPage(infoIndex)
|
||
if(dic == undefined){
|
||
return false
|
||
}
|
||
pageList.splice(index, 0, dic) // 列表添加
|
||
return true
|
||
}
|
||
|
||
// 增改: 在 pageList 的 index 处,删除该页面,改为 infoIndex 页。
|
||
function changePage(index, infoIndex){
|
||
const page = pageList[index]
|
||
// 删除旧页的python逻辑控制器
|
||
const flag = connector.delPage(page.ctrlKey)
|
||
if(!flag){
|
||
console.error("【Warning】删除页面失败:控制器["+page.ctrlKey+"]删除失败!")
|
||
// return false // 暂时不管控制器删除失败
|
||
}
|
||
const dic = newPage(infoIndex)
|
||
if(dic == undefined){
|
||
return false
|
||
}
|
||
page.obj.destroy() // 旧页对象删除
|
||
pageList[index] = dic // 替换新页
|
||
return true
|
||
}
|
||
|
||
// 删: 在 pageList 的 index 处,发送关闭指令。
|
||
function closePage(index){
|
||
pageList[index].obj.closePage()
|
||
}
|
||
|
||
// 删: 在 pageList 的 index 处,删除该页面。
|
||
function delPage(index){
|
||
const page = pageList[index]
|
||
// 删除python逻辑控制器
|
||
const flag = connector.delPage(page.ctrlKey)
|
||
if(!flag){
|
||
console.error("【Warning】删除页面失败:控制器["+page.ctrlKey+"]删除失败!")
|
||
// return false // 暂时不管控制器删除失败
|
||
}
|
||
page.obj.destroy() // 页对象删除
|
||
pageList.splice(index, 1) // 列表删除
|
||
return true
|
||
}
|
||
|
||
// 改: 展示 index 页。
|
||
function showPage(index){
|
||
// 遍历,将展示的页面设为可视状态,其他页面设为非可视状态
|
||
for(let i in pageList){
|
||
if(i==index){
|
||
pageList[i].obj.z = 0
|
||
pageList[i].obj.visible = true
|
||
pageList[i].obj.showPage()
|
||
}else{
|
||
pageList[i].obj.z = -1
|
||
pageList[i].obj.visible = false
|
||
}
|
||
}
|
||
}
|
||
|
||
// 改: 将一个原本在 index 的页移到 go 处。
|
||
function movePage(index, go){
|
||
var x = pageList.splice(index, 1)[0] // 删除
|
||
pageList.splice(go, 0, x) // 添加
|
||
}
|
||
|
||
// 查: 传入下标 index 列表 list 报错内容前缀 msg ,返回下标是否合法。
|
||
function isIndex(index, list, msg=""){
|
||
if(index<0 || index>=list.length){
|
||
if(msg)
|
||
console.error(msg+"下标"+index+"超出范围"+(pageList.length-1)+"!")
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
// ========================= 【辅助元素】 =========================
|
||
|
||
// 页巢,作为已生成的页组件对象的父级。可挂载到可视节点下来展示。
|
||
Item {
|
||
id: pagesNest
|
||
anchors.fill: parent
|
||
}
|
||
property var pagesNest: pagesNest
|
||
} |