When a .js module is used, every single file that imports it creates its own duplicated environment in memory for that module. Instead, use a simple QtObject with all the functions, and declare it in Window.qml so that it is available to all children everywhere in the app.
141 lines
4.0 KiB
QML
141 lines
4.0 KiB
QML
import QtQuick 2.12
|
|
import QtQuick.Controls 2.12
|
|
|
|
TextEdit {
|
|
id: label
|
|
font.family: theme.fontFamily.sans
|
|
font.pixelSize: theme.fontSize.normal
|
|
color: theme.colors.text
|
|
|
|
textFormat: Label.PlainText
|
|
tabStopDistance: 4 * 4 // 4 spaces
|
|
|
|
readOnly: true
|
|
persistentSelection: true
|
|
activeFocusOnPress: false
|
|
focus: false
|
|
|
|
onLinkActivated: Qt.openUrlExternally(link)
|
|
|
|
Component.onCompleted: updateSelection()
|
|
|
|
|
|
// If index is a whole number, the label will get two \n before itself
|
|
// in container.joinedSelection. If it's a decimal number, if gets one \n.
|
|
property real index
|
|
property HSelectableLabelContainer container
|
|
property bool selectable: true
|
|
|
|
|
|
function updateSelection() {
|
|
if (! selectable && label.selectedText) {
|
|
label.deselect()
|
|
updateContainerSelectedTexts()
|
|
return
|
|
}
|
|
|
|
if (! selectable) return
|
|
|
|
if (! container.reversed &&
|
|
container.selectionStart <= container.selectionEnd ||
|
|
|
|
container.reversed &&
|
|
container.selectionStart > container.selectionEnd)
|
|
{
|
|
var first = container.selectionStart
|
|
var firstPos = container.selectionStartPosition
|
|
var last = container.selectionEnd
|
|
var lastPos = container.selectionEndPosition
|
|
} else {
|
|
var first = container.selectionEnd
|
|
var firstPos = container.selectionEndPosition
|
|
var last = container.selectionStart
|
|
var lastPos = container.selectionStartPosition
|
|
}
|
|
|
|
if (first === index && last === index) {
|
|
select(
|
|
label.positionAt(firstPos.x, firstPos.y),
|
|
label.positionAt(lastPos.x, lastPos.y),
|
|
)
|
|
|
|
} else if ((! container.reversed && first < index && index < last) ||
|
|
(container.reversed && first > index && index > last))
|
|
{
|
|
label.selectAll()
|
|
|
|
} else if (first === index) {
|
|
label.select(positionAt(firstPos.x, firstPos.y), length)
|
|
|
|
} else if (last === index) {
|
|
label.select(0, positionAt(lastPos.x, lastPos.y))
|
|
|
|
} else {
|
|
label.deselect()
|
|
}
|
|
|
|
updateContainerSelectedTexts()
|
|
}
|
|
|
|
function updateContainerSelectedTexts() {
|
|
container.selectedTexts[index] = selectedText
|
|
container.selectedTextsChanged()
|
|
}
|
|
|
|
function selectWordAt(position) {
|
|
container.clearSelection()
|
|
label.cursorPosition = positionAt(position.x, position.y)
|
|
label.selectWord()
|
|
updateContainerSelectedTexts()
|
|
}
|
|
|
|
function selectAllText() {
|
|
container.clearSelection()
|
|
label.selectAll()
|
|
updateContainerSelectedTexts()
|
|
}
|
|
|
|
|
|
Connections {
|
|
target: container
|
|
onSelectionInfoChanged: updateSelection()
|
|
onDeselectAll: deselect()
|
|
}
|
|
|
|
DropArea {
|
|
anchors.fill: parent
|
|
onPositionChanged: {
|
|
if (! container.selecting) {
|
|
container.clearSelection()
|
|
container.selectionStart = index
|
|
container.selectionStartPosition = Qt.point(drag.x, drag.y)
|
|
container.selecting = true
|
|
} else {
|
|
container.selectionEnd = index
|
|
container.selectionEndPosition = Qt.point(drag.x, drag.y)
|
|
}
|
|
}
|
|
}
|
|
|
|
TapHandler {
|
|
acceptedButtons: Qt.LeftButton
|
|
onTapped: {
|
|
tapCount === 2 ? selectWordAt(eventPoint.position) :
|
|
tapCount === 3 ? selectAllText() :
|
|
container.clearSelection()
|
|
}
|
|
}
|
|
|
|
PointHandler {
|
|
onActiveChanged:
|
|
active ? container.dragStarted() : container.dragStopped()
|
|
onPointChanged: container.dragPointChanged(point)
|
|
}
|
|
|
|
MouseArea {
|
|
anchors.fill: label
|
|
acceptedButtons: Qt.NoButton
|
|
cursorShape: label.hoveredLink ? Qt.PointingHandCursor : Qt.IBeamCursor
|
|
}
|
|
}
|