Add context menu to copy selected messages
This commit is contained in:
parent
016f76167f
commit
131a20e9c5
5
TODO.md
5
TODO.md
|
@ -1,6 +1,9 @@
|
||||||
- Message selection
|
- Message selection
|
||||||
|
- Copying messages (shortcut)
|
||||||
|
- Copy names
|
||||||
|
- Copy text with triple click, copy text + name + date with quadruple click
|
||||||
|
- Copy to X11 selection
|
||||||
- Make scroll wheel usable
|
- Make scroll wheel usable
|
||||||
- Copying messages (menu & shortcut)
|
|
||||||
|
|
||||||
- Refactoring
|
- Refactoring
|
||||||
- Banners
|
- Banners
|
||||||
|
|
1
src/icons/thin/copy.svg
Normal file
1
src/icons/thin/copy.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M7 13h10v1h-10v-1zm15-11v22h-20v-22h3c1.229 0 2.18-1.084 3-2h8c.82.916 1.771 2 3 2h3zm-11 1c0 .552.448 1 1 1s1-.448 1-1-.448-1-1-1-1 .448-1 1zm9 15.135c-1.073 1.355-2.448 2.763-3.824 3.865h3.824v-3.865zm0-14.135h-4l-2 2h-3.898l-2.102-2h-4v18h7.362c4.156 0 2.638-6 2.638-6s6 1.65 6-2.457v-9.543zm-13 12h5v-1h-5v1zm0-4h10v-1h-10v1zm0-2h10v-1h-10v1z"/></svg>
|
After Width: | Height: | Size: 447 B |
|
@ -1,4 +1,5 @@
|
||||||
import QtQuick 2.12
|
import QtQuick 2.12
|
||||||
|
import "../utils.js" as Utils
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
signal deselectAll()
|
signal deselectAll()
|
||||||
|
@ -20,8 +21,21 @@ Item {
|
||||||
selectionEnd, selectionEndPosition,
|
selectionEnd, selectionEndPosition,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
readonly property string joinedSelection: {
|
||||||
|
let toCopy = []
|
||||||
|
|
||||||
|
for (let key of Object.keys(selectedTexts).sort()) {
|
||||||
|
if (selectedTexts[key]) toCopy.push(selectedTexts[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reversed) toCopy.reverse()
|
||||||
|
|
||||||
|
return toCopy.join("\n\n")
|
||||||
|
}
|
||||||
|
|
||||||
readonly property alias dragPoint: dragHandler.centroid
|
readonly property alias dragPoint: dragHandler.centroid
|
||||||
readonly property alias dragPosition: dragHandler.centroid.position
|
readonly property alias dragPosition: dragHandler.centroid.position
|
||||||
|
readonly property alias contextMenu: contextMenu
|
||||||
|
|
||||||
|
|
||||||
function clearSelection() {
|
function clearSelection() {
|
||||||
|
@ -33,17 +47,6 @@ Item {
|
||||||
deselectAll()
|
deselectAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
function copySelection() {
|
|
||||||
let toCopy = []
|
|
||||||
|
|
||||||
for (let key of Object.keys(selectedTexts).sort()) {
|
|
||||||
if (selectedTexts[key]) toCopy.push(selectedTexts[key])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call some function to copy to clipboard here instead
|
|
||||||
print("Copy: <" + toCopy.join("\n\n") + ">")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Item { id: dragPoint }
|
Item { id: dragPoint }
|
||||||
|
|
||||||
|
@ -61,12 +64,30 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TapHandler {
|
|
||||||
acceptedButtons: Qt.LeftButton
|
|
||||||
onTapped: clearSelection()
|
|
||||||
}
|
|
||||||
|
|
||||||
PointHandler {
|
PointHandler {
|
||||||
id: pointHandler
|
id: pointHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TapHandler {
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
onTapped: clearSelection()
|
||||||
|
onLongPressed: contextMenu.popup()
|
||||||
|
}
|
||||||
|
|
||||||
|
TapHandler {
|
||||||
|
acceptedButtons: Qt.RightButton
|
||||||
|
onTapped: contextMenu.popup()
|
||||||
|
onLongPressed: contextMenu.popup()
|
||||||
|
}
|
||||||
|
|
||||||
|
HMenu {
|
||||||
|
id: contextMenu
|
||||||
|
|
||||||
|
HMenuItem {
|
||||||
|
icon.name: "copy"
|
||||||
|
text: qsTr("Copy")
|
||||||
|
enabled: Boolean(joinedSelection)
|
||||||
|
onTriggered: Utils.copyToClipboard(joinedSelection)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ Rectangle {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: dragFlicker
|
id: dragFlicker
|
||||||
interval: 100
|
interval: 100
|
||||||
|
|
|
@ -8,7 +8,6 @@ import "SidePane"
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: mainUI
|
id: mainUI
|
||||||
|
|
||||||
Component.onCompleted: window.mainUI = mainUI
|
Component.onCompleted: window.mainUI = mainUI
|
||||||
|
|
||||||
property alias shortcuts: shortcuts
|
property alias shortcuts: shortcuts
|
||||||
|
|
|
@ -27,8 +27,17 @@ ApplicationWindow {
|
||||||
|
|
||||||
property var theme: null
|
property var theme: null
|
||||||
|
|
||||||
|
readonly property alias py: py
|
||||||
|
readonly property alias pseudoClipboard: pseudoClipboard
|
||||||
|
|
||||||
Python { id: py }
|
Python { id: py }
|
||||||
|
|
||||||
|
TextEdit {
|
||||||
|
id: pseudoClipboard
|
||||||
|
visible: false
|
||||||
|
readOnly: true
|
||||||
|
}
|
||||||
|
|
||||||
HLoader {
|
HLoader {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
source: py.ready ? "" : "LoadingScreen.qml"
|
source: py.ready ? "" : "LoadingScreen.qml"
|
||||||
|
@ -38,7 +47,6 @@ ApplicationWindow {
|
||||||
// true makes the initially loaded chat page invisible for some reason
|
// true makes the initially loaded chat page invisible for some reason
|
||||||
asynchronous: false
|
asynchronous: false
|
||||||
|
|
||||||
id: uiLoader
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
scale: py.ready ? 1 : 0.5
|
scale: py.ready ? 1 : 0.5
|
||||||
source: py.ready ? (Qt.application.arguments[1] || "UI.qml") : ""
|
source: py.ready ? (Qt.application.arguments[1] || "UI.qml") : ""
|
||||||
|
|
|
@ -182,6 +182,7 @@ function smartVerticalFlick(flickable, baseVelocity, fastMultiply=4) {
|
||||||
flickable.flick(0, baseVelocity * (fast ? fastMultiply : 1))
|
flickable.flick(0, baseVelocity * (fast ? fastMultiply : 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function flickToTop(flickable) {
|
function flickToTop(flickable) {
|
||||||
if (! flickable.interactive) return
|
if (! flickable.interactive) return
|
||||||
if (flickable.visibleArea.yPosition < 0) return
|
if (flickable.visibleArea.yPosition < 0) return
|
||||||
|
@ -191,6 +192,7 @@ function flickToTop(flickable) {
|
||||||
flickable.flick(0, -100) // Force the delegates to load
|
flickable.flick(0, -100) // Force the delegates to load
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function flickToBottom(flickable) {
|
function flickToBottom(flickable) {
|
||||||
if (! flickable.interactive) return
|
if (! flickable.interactive) return
|
||||||
if (flickable.visibleArea.yPosition < 0) return
|
if (flickable.visibleArea.yPosition < 0) return
|
||||||
|
@ -199,3 +201,10 @@ function flickToBottom(flickable) {
|
||||||
flickable.returnToBounds()
|
flickable.returnToBounds()
|
||||||
flickable.flick(0, 100)
|
flickable.flick(0, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function copyToClipboard(text) {
|
||||||
|
window.pseudoClipboard.text = text
|
||||||
|
window.pseudoClipboard.selectAll()
|
||||||
|
window.pseudoClipboard.copy()
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user