Skip to content

Commit 03dae89

Browse files
committed
基本实现跨文本框多选、全选、快捷复制 (#18)
1 parent e81abab commit 03dae89

File tree

2 files changed

+87
-36
lines changed

2 files changed

+87
-36
lines changed

UmiOCR-data/qt_res/qml/Widgets/ResultLayout/ResultTextContainer.qml

+34
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ Item {
1818
property int selectL: -1
1919
property int selectR: -1
2020
property int selectUpdate: 0 // 只要有变化,就刷新选中
21+
// 全全选和全复制
22+
property var copy: undefined
23+
property var copyAll: undefined
24+
property var selectAll: undefined
2125

2226
// 传入一个相对于item的坐标,返回该坐标位于this组件的什么位置。
2327
// undefined:不在组件中 | -1:顶部信息栏 | 0~N:所在字符的下标
@@ -119,6 +123,36 @@ Item {
119123
color: status_==="error"? theme.noColor:theme.textColor
120124
font.pixelSize: size_.text
121125
font.family: theme.dataFontFamily
126+
127+
// 按键事件。响应并拦截:单双击 Ctrl+C ,双击 Ctrl+A
128+
property int keyUpTime: -1 // 上次按键抬起的时间戳。需要截取后8位以免int放不下
129+
property int keyDoubleTime: 300 // 双击毫秒
130+
Keys.onPressed: {
131+
if (event.modifiers & Qt.ControlModifier) {
132+
if (event.key === Qt.Key_C) {
133+
event.accepted = true // 拦截按键
134+
const t = Date.now() & 0xFFFFFFFF
135+
if(t - keyUpTime <= keyDoubleTime) { // 短时间内抬起按下,属于双击
136+
resultRoot.copyAll && resultRoot.copyAll()
137+
}
138+
else {
139+
resultRoot.copy && resultRoot.copy()
140+
}
141+
}
142+
else if(event.key === Qt.Key_A) {
143+
const t = Date.now() & 0xFFFFFFFF
144+
if(t - keyUpTime <= keyDoubleTime) {
145+
event.accepted = true
146+
resultRoot.selectAll && resultRoot.selectAll()
147+
}
148+
}
149+
}
150+
}
151+
Keys.onReleased: {
152+
if (event.key === Qt.Key_A || event.key === Qt.Key_C) {
153+
keyUpTime = Date.now() & 0xFFFFFFFF
154+
}
155+
}
122156
}
123157
}
124158
}

UmiOCR-data/qt_res/qml/Widgets/ResultLayout/ResultsTableView.qml

+53-36
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ Item {
147147
onTextMainChanged: {
148148
resultsModel.setProperty(index, "resText", textMain) // 文字改变时写入列表
149149
}
150+
copy: tableMouseArea.selectCopy
151+
copyAll: tableMouseArea.selectAllCopy
152+
selectAll: tableMouseArea.selectAll
150153
}
151154
// 滚动条
152155
ScrollBar.vertical: ScrollBar { id:scrollBar }
@@ -203,7 +206,7 @@ Item {
203206
}
204207
return [li, lt, ri, rt]
205208
}
206-
// 根据 Index 的参数,选择对应文本。返回选取类型:
209+
// 根据 Index 的参数,选择对应文本。
207210
function selectIndex() {
208211
const lr = getIndexes()
209212
const li=lr[0], lt=lr[1], ri=lr[2], rt=lr[3]
@@ -235,6 +238,40 @@ Item {
235238
}
236239
selectUpdate++
237240
}
241+
// 全选
242+
function selectAll() {
243+
if(resultsModel.count === 0) return
244+
startIndex = startTextIndex = 0
245+
endIndex = resultsModel.count-1
246+
endTextIndex = resultsModel.get(endIndex).resText.length
247+
selectIndex()
248+
}
249+
// 复制已选中的内容
250+
function selectCopy() {
251+
const lr = getIndexes()
252+
const li=lr[0], lt=lr[1], ri=lr[2], rt=lr[3]
253+
if(li < 0 || ri < 0) return
254+
let copyText = ""
255+
for(let i = li; i <= ri; i++) {
256+
let item = resultsModel.get(i)
257+
if(i === li && i === ri) // 单个块
258+
copyText = item.resText.substring(lt, rt)
259+
else if(i === li) // 多个块的起始
260+
copyText = item.resText.substring(lt)+"\n"
261+
else if(i === ri) // 多个块的结束
262+
copyText += item.resText.substring(0, rt)
263+
else // 多个块的中间
264+
copyText += item.resText+"\n"
265+
}
266+
if(copyText && copyText.length>0) {
267+
qmlapp.utilsConnector.copyText(copyText)
268+
}
269+
}
270+
// 复制所有
271+
function selectAllCopy() {
272+
selectAll()
273+
selectCopy()
274+
}
238275
// 按下
239276
onPressed: {
240277
const info = getWhere()
@@ -270,48 +307,17 @@ Item {
270307
onReleased: {
271308
const info = getWhere()
272309
if(info===undefined || info.where<0) {
273-
startIndex=startTextIndex=endIndex=endTextIndex-1
310+
selectIndex()
274311
return
275312
}
276313
endIndex = info.index
277314
endTextIndex = info.where
278-
if(startIndex!==endIndex) { // 多块选中,预先激活本元素焦点,准备接收键盘事件
279-
tableMouseArea.forceActiveFocus()
280-
}
281315
selectIndex() // 选中
282316
if(startIndex===endIndex && startTextIndex===endTextIndex) {
283317
info.obj.focus(info.where) // 单击移动光标
284318
}
285-
else if(startIndex===endIndex) {
286-
info.obj.focus(-1) // 单块选中,激活焦点
287-
}
288-
}
289-
// 按键事件
290-
Keys.onPressed: {
291-
if (event.modifiers & Qt.ControlModifier) {
292-
// 复制
293-
if (event.key === Qt.Key_C) {
294-
console.log("== copy: ")
295-
const lr = getIndexes()
296-
const li=lr[0], lt=lr[1], ri=lr[2], rt=lr[3]
297-
if(li < 0 || ri < 0) return
298-
let copyText = ""
299-
for(let i = li; i <= ri; i++) {
300-
let item = resultsModel.get(i)
301-
if(i === li && i === ri) // 单个块
302-
copyText = item.resText.substring(lt, rt)
303-
else if(i === li) // 多个块的起始
304-
copyText = item.resText.substring(lt)+"\n"
305-
else if(i === ri) // 多个块的结束
306-
copyText += item.resText.substring(0, rt)
307-
else // 多个块的中间
308-
copyText += item.resText+"\n"
309-
}
310-
if(copyText && copyText.length>0) {
311-
console.log("== copy", copyText)
312-
qmlapp.utilsConnector.copyText(copyText)
313-
}
314-
}
319+
else {
320+
info.obj.focus(-1) // 激活焦点
315321
}
316322
}
317323
}
@@ -334,10 +340,21 @@ Item {
334340
resultsModel.clear()
335341
}
336342
}
337-
CheckButton {
343+
Button_ {
344+
id: ctrlBtn2
338345
anchors.top: parent.top
339346
anchors.bottom: parent.bottom
340347
anchors.right: ctrlBtn1.left
348+
text_: qsTr("操作")
349+
toolTip: qsTr("鼠标拖拽:可选中多个文本框的内容\nCtrl+A单击:全选单个文本框的内容\nCtrl+A双击:全选所有文本框的内容\nCtrl+C单击:复制选中的内容\nCtrl+C双击:全选所有文本框并复制")
350+
onClicked: {
351+
tableMouseArea.selectAllCopy()
352+
}
353+
}
354+
CheckButton {
355+
anchors.top: parent.top
356+
anchors.bottom: parent.bottom
357+
anchors.right: ctrlBtn2.left
341358
text_: qsTr("滚动")
342359
toolTip: qsTr("自动滚动到底部")
343360
textColor_: autoToBottom ? theme.textColor : theme.subTextColor

0 commit comments

Comments
 (0)