464 lines
17 KiB
QML
464 lines
17 KiB
QML
|
|
// ==============================================
|
|||
|
|
// =============== 功能页:二维码 ===============
|
|||
|
|
// ==============================================
|
|||
|
|
|
|||
|
|
import QtQuick 2.15
|
|||
|
|
|
|||
|
|
import ".."
|
|||
|
|
import "../../Widgets"
|
|||
|
|
import "../../Widgets/ResultLayout"
|
|||
|
|
import "../../Widgets/ImageViewer"
|
|||
|
|
|
|||
|
|
TabPage {
|
|||
|
|
id: tabPage
|
|||
|
|
// 配置
|
|||
|
|
configsComp: QRCodeConfigs {
|
|||
|
|
// 修改配置信号触发后,延迟一个事件循环,重新生成二维码图片
|
|||
|
|
onReBarcode: Qt.callLater(reWriteBarcode)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ========================= 【逻辑】 =========================
|
|||
|
|
|
|||
|
|
// 开始截图
|
|||
|
|
function screenshot() {
|
|||
|
|
qmlapp.imageManager.screenshot(screenshotEnd)
|
|||
|
|
}
|
|||
|
|
// 截图完毕
|
|||
|
|
function screenshotEnd(clipID) {
|
|||
|
|
popMainWindow()
|
|||
|
|
if(!clipID) {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
const configDict = configsComp.getValueDict()
|
|||
|
|
tabPage.callPy("scanImgID", clipID, configDict)
|
|||
|
|
qmlapp.tab.showTabPageObj(tabPage) // 切换标签页
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 开始粘贴
|
|||
|
|
function paste() {
|
|||
|
|
popMainWindow()
|
|||
|
|
const res = qmlapp.imageManager.getPaste()
|
|||
|
|
if(res.error) {
|
|||
|
|
qmlapp.popup.simple(qsTr("获取剪贴板异常"), res.error)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
if(res.text) {
|
|||
|
|
qmlapp.popup.simple(qsTr("剪贴板中为文本"), res.text)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
qmlapp.tab.showTabPageObj(tabPage) // 切换标签页
|
|||
|
|
if(res.imgID) { // 图片
|
|||
|
|
imageText.showImgID(res.imgID)
|
|||
|
|
const configDict = configsComp.getValueDict()
|
|||
|
|
tabPage.callPy("scanImgID", res.imgID, configDict)
|
|||
|
|
}
|
|||
|
|
else if(res.paths) { // 地址
|
|||
|
|
scanPaths(res.paths)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 异步加载一批图像路径
|
|||
|
|
function scanPaths(paths) {
|
|||
|
|
qmlapp.asynFilesLoader.run(paths,"image",false,onScanPaths)
|
|||
|
|
}
|
|||
|
|
// 完毕后,对合法路径进行扫码
|
|||
|
|
function onScanPaths(paths) {
|
|||
|
|
if(!paths || paths.length < 1) {
|
|||
|
|
qmlapp.popup.simple(qsTr("无有效图片"), "")
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
const configDict = configsComp.getValueDict()
|
|||
|
|
const simpleType = configDict["other.simpleNotificationType"]
|
|||
|
|
qmlapp.popup.simple(qsTr("导入%1条图片路径").arg(paths.length), "", simpleType)
|
|||
|
|
imageText.showPath(paths[0])
|
|||
|
|
tabPage.callPy("scanPaths", paths, configDict)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 弹出主窗口
|
|||
|
|
function popMainWindow() {
|
|||
|
|
// 若主窗口已经可见,则不处理
|
|||
|
|
if(qmlapp.mainWin.getVisibility())
|
|||
|
|
return
|
|||
|
|
// 等一回合再弹,防止与收回截图窗口相冲突
|
|||
|
|
if(configsComp.getValue("action.popMainWindow")) {
|
|||
|
|
Qt.callLater(()=>{
|
|||
|
|
qmlapp.mainWin.loadGeometry(false)
|
|||
|
|
qmlapp.mainWin.setVisibility(true)
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 生成二维码
|
|||
|
|
function writeBarcode(text) {
|
|||
|
|
if(!text || text.length===0)
|
|||
|
|
return
|
|||
|
|
setRunning(true)
|
|||
|
|
const configDict = configsComp.getValueDict()
|
|||
|
|
const format = configDict["writeBarcode.format"]
|
|||
|
|
const w = configDict["writeBarcode.width"]
|
|||
|
|
const h = configDict["writeBarcode.height"]
|
|||
|
|
const quiet_zone = configDict["writeBarcode.quiet_zone"]
|
|||
|
|
const ec_level = configDict["writeBarcode.ec_level"]
|
|||
|
|
const imgID = tabPage.callPy("writeBarcode", text, format, w, h, quiet_zone, ec_level)
|
|||
|
|
setRunning(false)
|
|||
|
|
if(imgID.startsWith("[Error]") || imgID.startsWith("[Warning]")) {
|
|||
|
|
if(imgID.startsWith("[Error] [")) {
|
|||
|
|
const msg = qsTr("参数有误,或输入内容不合规定。请参照报错指示修改:") +"\n"+ imgID
|
|||
|
|
qmlapp.popup.message(qsTr("生成二维码失败"), msg, "error")
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
qmlapp.popup.message(qsTr("生成二维码失败"), imgID, "error")
|
|||
|
|
}
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
imageText.showImgID(imgID)
|
|||
|
|
}
|
|||
|
|
// 立刻重新生成二维码图片
|
|||
|
|
function reWriteBarcode() {
|
|||
|
|
writeBarcode(writeEdit.text)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// ========================= 【python调用qml】 =========================
|
|||
|
|
|
|||
|
|
// 获取一个扫码的返回值
|
|||
|
|
function onQRCodeGet(res, imgID="", imgPath="") {
|
|||
|
|
// 添加到结果
|
|||
|
|
if(imgID) // 图片类型
|
|||
|
|
imageText.showImgID(imgID)
|
|||
|
|
else if(imgPath) // 地址类型
|
|||
|
|
imageText.showPath(imgPath)
|
|||
|
|
// 路径转文件名
|
|||
|
|
const parts = imgPath.split("/")
|
|||
|
|
res.title = parts[parts.length - 1]
|
|||
|
|
imageText.showTextBoxes(res)
|
|||
|
|
const resText = resultsTableView.addOcrResult(res)
|
|||
|
|
// 若tabPanel面板的下标没有变化过,则切换到记录页
|
|||
|
|
if(tabPanel.indexChangeNum < 2)
|
|||
|
|
tabPanel.currentIndex = 1
|
|||
|
|
// 复制到剪贴板
|
|||
|
|
const copy = configsComp.getValue("action.copy")
|
|||
|
|
if(copy && resText!="")
|
|||
|
|
qmlapp.utilsConnector.copyText(resText)
|
|||
|
|
// 弹出通知
|
|||
|
|
showSimple(res, resText, copy)
|
|||
|
|
// 升起主窗口
|
|||
|
|
popMainWindow()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 任务完成后发送通知
|
|||
|
|
function showSimple(res, resText, isCopy) {
|
|||
|
|
// 获取弹窗类型
|
|||
|
|
let simpleType = configsComp.getValue("other.simpleNotificationType")
|
|||
|
|
if(simpleType==="default") {
|
|||
|
|
simpleType = qmlapp.globalConfigs.getValue("window.simpleNotificationType")
|
|||
|
|
}
|
|||
|
|
const code = res.code
|
|||
|
|
const time = res.time.toFixed(2)
|
|||
|
|
let title = ""
|
|||
|
|
resText = resText.replace(/\n/g, " ") // 换行符替换空格
|
|||
|
|
if(code === 100 || code === 101) { // 成功时,不发送内部弹窗
|
|||
|
|
if(simpleType==="inside" || simpleType==="onlyInside")
|
|||
|
|
if(qmlapp.mainWin.getVisibility())
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
if(code === 100) {
|
|||
|
|
if(isCopy) title = qsTr("已复制到剪贴板")
|
|||
|
|
else title = qsTr("识图完成")
|
|||
|
|
}
|
|||
|
|
else if(code === 101) {
|
|||
|
|
title = qsTr("无文字")
|
|||
|
|
resText = ""
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
title = qsTr("识别失败")
|
|||
|
|
}
|
|||
|
|
title += ` - ${time}s`
|
|||
|
|
qmlapp.popup.simple(title, resText, simpleType)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 设置运行状态
|
|||
|
|
function setRunning(flag) {
|
|||
|
|
running = flag
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ========================= 【事件管理】 =========================
|
|||
|
|
|
|||
|
|
Component.onCompleted: {
|
|||
|
|
eventSub() // 订阅事件
|
|||
|
|
}
|
|||
|
|
// 关闭页面
|
|||
|
|
function closePage() {
|
|||
|
|
eventUnsub()
|
|||
|
|
delPage()
|
|||
|
|
}
|
|||
|
|
// 订阅事件
|
|||
|
|
function eventSub() {
|
|||
|
|
qmlapp.pubSub.subscribeGroup("<<qrcode_screenshot>>", this, "screenshot", ctrlKey)
|
|||
|
|
qmlapp.pubSub.subscribeGroup("<<qrcode_paste>>", this, "paste", ctrlKey)
|
|||
|
|
qmlapp.systemTray.addMenuItem("<<qrcode_screenshot>>", qsTr("扫描二维码"), screenshot)
|
|||
|
|
}
|
|||
|
|
// 取消订阅事件
|
|||
|
|
function eventUnsub() {
|
|||
|
|
qmlapp.systemTray.delMenuItem("<<qrcode_screenshot>>")
|
|||
|
|
qmlapp.pubSub.unsubscribeGroup(ctrlKey)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ========================= 【布局】 =========================
|
|||
|
|
property bool running: false
|
|||
|
|
// 主区域:可切换双栏面板
|
|||
|
|
DoubleSwitchableLayout {
|
|||
|
|
id: doubleLayout
|
|||
|
|
saveKey: "QRCode_1"
|
|||
|
|
anchors.fill: parent
|
|||
|
|
|
|||
|
|
// 面板A:图像展示
|
|||
|
|
itemA: Panel {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
clip: true
|
|||
|
|
// 顶部控制栏
|
|||
|
|
Item {
|
|||
|
|
id: dLeftTop
|
|||
|
|
anchors.top: parent.top
|
|||
|
|
anchors.left: parent.left
|
|||
|
|
anchors.right: parent.right
|
|||
|
|
anchors.margins: size_.spacing
|
|||
|
|
height: size_.line * 1.5
|
|||
|
|
// 靠右
|
|||
|
|
Row {
|
|||
|
|
id: dLeftTopR
|
|||
|
|
anchors.top: parent.top
|
|||
|
|
anchors.right: parent.right
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
spacing: size_.smallSpacing
|
|||
|
|
|
|||
|
|
IconButtonBar {
|
|||
|
|
anchors.top: parent.top
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
btnList: [
|
|||
|
|
{
|
|||
|
|
icon: "menu",
|
|||
|
|
onClicked: imageText.popupMenu,
|
|||
|
|
toolTip: tr("右键菜单"),
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
icon: "save",
|
|||
|
|
onClicked: imageText.saveImage,
|
|||
|
|
toolTip: tr("保存图片"),
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
icon: "full_screen",
|
|||
|
|
onClicked: imageText.imageFullFit,
|
|||
|
|
toolTip: tr("图片大小:适应窗口"),
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
icon: "one_to_one",
|
|||
|
|
onClicked: imageText.imageScaleAddSub,
|
|||
|
|
toolTip: tr("图片大小:实际"),
|
|||
|
|
},
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
// 百分比显示
|
|||
|
|
Text_ {
|
|||
|
|
anchors.top: parent.top
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
verticalAlignment: Text.AlignVCenter
|
|||
|
|
horizontalAlignment: Text.AlignRight
|
|||
|
|
text: (imageText.scale*100).toFixed(0) + "%"
|
|||
|
|
color: theme.subTextColor
|
|||
|
|
width: size_.line * 2.5
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 靠左
|
|||
|
|
Rectangle { // 背景
|
|||
|
|
anchors.left: parent.left
|
|||
|
|
anchors.top: parent.top
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
width: dLeftTopL.width
|
|||
|
|
color: theme.bgColor
|
|||
|
|
Rectangle {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
color: theme.coverColor1
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
Row {
|
|||
|
|
id: dLeftTopL
|
|||
|
|
anchors.left: parent.left
|
|||
|
|
anchors.top: parent.top
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
spacing: size_.smallSpacing
|
|||
|
|
|
|||
|
|
IconButtonBar {
|
|||
|
|
anchors.top: parent.top
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
btnList: [
|
|||
|
|
{
|
|||
|
|
icon: "screenshot",
|
|||
|
|
onClicked: tabPage.screenshot,
|
|||
|
|
color: theme.textColor,
|
|||
|
|
bgColor: theme.bgColor,
|
|||
|
|
text: tr("截图"),
|
|||
|
|
toolTip: tr("屏幕截图"),
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
icon: "paste",
|
|||
|
|
onClicked: tabPage.paste,
|
|||
|
|
color: theme.textColor,
|
|||
|
|
bgColor: theme.bgColor,
|
|||
|
|
text: tr("粘贴"),
|
|||
|
|
toolTip: tr("粘贴图片"),
|
|||
|
|
},
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 图片预览区域
|
|||
|
|
ImageWithText {
|
|||
|
|
id: imageText
|
|||
|
|
anchors.top: dLeftTop.bottom
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
anchors.left: parent.left
|
|||
|
|
anchors.right: parent.right
|
|||
|
|
anchors.margins: size_.spacing
|
|||
|
|
anchors.topMargin: size_.smallSpacing
|
|||
|
|
|
|||
|
|
// 加载中 动态图标
|
|||
|
|
Loading {
|
|||
|
|
text: "Running"
|
|||
|
|
visible: running
|
|||
|
|
anchors.centerIn: parent
|
|||
|
|
}
|
|||
|
|
// 提示
|
|||
|
|
DefaultTips {
|
|||
|
|
visibleFlag: running
|
|||
|
|
anchors.fill: parent
|
|||
|
|
tips: qsTr("截图、拖入或粘贴二维码图片")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 面板B:结果
|
|||
|
|
itemB: Panel {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
|
|||
|
|
TabPanel {
|
|||
|
|
id: tabPanel
|
|||
|
|
anchors.fill: parent
|
|||
|
|
anchors.margins: size_.spacing
|
|||
|
|
isMenuTop: doubleLayout.isRow // 左右布局时,菜单在顶部;上下布局时菜单在底部
|
|||
|
|
menuHeight: size_.line * 1.5
|
|||
|
|
|
|||
|
|
// 结果面板
|
|||
|
|
ResultsTableView {
|
|||
|
|
id: resultsTableView
|
|||
|
|
anchors.fill: parent
|
|||
|
|
visible: false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//生成面板
|
|||
|
|
Item {
|
|||
|
|
id: writePanel
|
|||
|
|
anchors.fill: parent
|
|||
|
|
visible: false
|
|||
|
|
Item {
|
|||
|
|
id: writePanelTop
|
|||
|
|
anchors.top: parent.top
|
|||
|
|
anchors.left: parent.left
|
|||
|
|
anchors.right: parent.right
|
|||
|
|
height: size_.line * 1.5
|
|||
|
|
|
|||
|
|
Button_ {
|
|||
|
|
id: writePanelBtn1
|
|||
|
|
anchors.top: parent.top
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
anchors.left: parent.left
|
|||
|
|
text_: qsTr("设置")
|
|||
|
|
onClicked: {
|
|||
|
|
tabPanel.currentIndex = 0 // 转到设置面板
|
|||
|
|
configsComp.panelComponent.scrollToGroup(3) // 滚动到生成设置
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
Row {
|
|||
|
|
anchors.top: parent.top
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
anchors.right: parent.right
|
|||
|
|
CheckButton {
|
|||
|
|
anchors.top: parent.top
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
text_: qsTr("自动刷新")
|
|||
|
|
toolTip: qsTr("修改文字后,自动生成二维码/条形码")
|
|||
|
|
visible: writePanelTop.width > writePanelBtn1.width+writePanelBtn2.width+this.width
|
|||
|
|
textColor_: theme.textColor
|
|||
|
|
checked: writeEdit.autoUpdate
|
|||
|
|
enabledAnime: true
|
|||
|
|
onCheckedChanged: {
|
|||
|
|
writeEdit.autoUpdate = checked
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
Button_ {
|
|||
|
|
id: writePanelBtn2
|
|||
|
|
anchors.top: parent.top
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
text_: qsTr("刷新")
|
|||
|
|
toolTip: qsTr("生成二维码/条形码")
|
|||
|
|
onClicked: reWriteBarcode()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
Rectangle {
|
|||
|
|
anchors.top: writePanelTop.bottom
|
|||
|
|
anchors.left: parent.left
|
|||
|
|
anchors.right: parent.right
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
anchors.topMargin: size_.smallSpacing
|
|||
|
|
color: theme.bgColor
|
|||
|
|
border.width: 1
|
|||
|
|
border.color: theme.coverColor4
|
|||
|
|
TextEdit_ {
|
|||
|
|
id: writeEdit
|
|||
|
|
anchors.fill: parent
|
|||
|
|
anchors.margins: size_.spacing
|
|||
|
|
// 自动刷新
|
|||
|
|
property bool autoUpdate: true
|
|||
|
|
// 文字输入改变时,等待一段时间,自动刷新
|
|||
|
|
Timer {
|
|||
|
|
id: writeEditTimer
|
|||
|
|
interval: 500 // 0.5 秒
|
|||
|
|
repeat: false
|
|||
|
|
onTriggered: reWriteBarcode()
|
|||
|
|
}
|
|||
|
|
onTextChanged: {
|
|||
|
|
if(autoUpdate) // 重启计时器
|
|||
|
|
writeEditTimer.restart()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
tabsModel: [
|
|||
|
|
{
|
|||
|
|
"key": "configs",
|
|||
|
|
"title": qsTr("设置"),
|
|||
|
|
"component": configsComp.panelComponent,
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"key": "ocrResult",
|
|||
|
|
"title": qsTr("记录"),
|
|||
|
|
"component": resultsTableView,
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"key": "writePanel",
|
|||
|
|
"title": qsTr("生成"),
|
|||
|
|
"component": writePanel,
|
|||
|
|
},
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 鼠标拖入图片
|
|||
|
|
DropArea_ {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
callback: tabPage.scanPaths
|
|||
|
|
}
|
|||
|
|
}
|