Warning, /multimedia/kdenlive/src/timeline2/view/qml/SubTitle.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-FileCopyrightText: 2020-2021 Jean-Baptiste Mardelle 0003 SPDX-FileCopyrightText: 2020 Sashmita Raghav 0004 0005 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0006 */ 0007 import QtQuick 2.15 0008 import QtQuick.Controls 2.15 0009 import com.enums 1.0 0010 0011 Item { 0012 id: subtitleRoot 0013 visible : true 0014 z: selected ? 30 : 20 0015 property int oldStartX 0016 property int startFrame 0017 property int endFrame 0018 property int subId 0019 property int duration : endFrame - startFrame 0020 property double tScale: root.timeScale 0021 property string subtitle 0022 property bool selected 0023 property bool isGrabbed: false 0024 height: subtitleTrack.height 0025 0026 function editText() 0027 { 0028 subtitleBase.textEditBegin = true 0029 } 0030 0031 onStartFrameChanged: { 0032 if (!subtitleClipArea.pressed) { 0033 subtitleClipArea.x = startFrame * root.timeScale 0034 } 0035 } 0036 0037 onTScaleChanged: { 0038 subtitleClipArea.x = startFrame * root.timeScale; 0039 } 0040 0041 onIsGrabbedChanged: { 0042 if (subtitleRoot.isGrabbed) { 0043 grabItem() 0044 } else { 0045 timeline.showToolTip() 0046 subtitleClipArea.focus = false 0047 } 0048 } 0049 0050 onSelectedChanged: { 0051 if (!selected && isGrabbed) { 0052 //timeline.grabCurrent() 0053 } 0054 if (subtitleBase.textEditBegin) { 0055 // End editing on focus change 0056 subtitleBase.textEditBegin = false 0057 } 0058 } 0059 0060 function grabItem() { 0061 subtitleClipArea.forceActiveFocus() 0062 subtitleClipArea.focus = true 0063 } 0064 0065 MouseArea { 0066 // Clip shifting 0067 id: subtitleClipArea 0068 x: startFrame * root.timeScale 0069 height: parent.height 0070 width: subtitleBase.width 0071 hoverEnabled: true 0072 enabled: true 0073 property int newStart: -1 0074 property int diff: -1 0075 property int oldStartFrame 0076 property int snappedFrame 0077 // Used for continuous scrolling 0078 property int incrementalOffset 0079 property double delta: -1 0080 property double oldDelta: 0 0081 property bool startMove: false 0082 visible: root.activeTool === 0 0083 acceptedButtons: Qt.LeftButton | Qt.RightButton 0084 cursorShape: (pressed ? Qt.ClosedHandCursor : ((startMouseArea.drag.active || endMouseArea.drag.active)? Qt.SizeHorCursor: Qt.PointingHandCursor)); 0085 drag.axis: Drag.XAxis 0086 drag.smoothed: false 0087 drag.minimumX: 0 0088 onEntered: { 0089 console.log('ENTERED SUBTITLE MOUSE AREA') 0090 timeline.showKeyBinding(i18n("<b>Double click</b> to edit text")) 0091 } 0092 onExited: { 0093 timeline.showKeyBinding() 0094 } 0095 onPressed: mouse => { 0096 console.log('ENTERED ITEM CLCKD:', subtitleRoot.subtitle, ' ID: ', subtitleRoot.subId, 'START FRM: ', subtitleRoot.startFrame) 0097 root.autoScrolling = false 0098 oldStartX = scrollView.contentX + mapToItem(scrollView, mouseX, 0).x 0099 oldStartFrame = subtitleRoot.startFrame 0100 snappedFrame = oldStartFrame 0101 x = subtitleBase.x 0102 startMove = mouse.button & Qt.LeftButton 0103 if (startMove) { 0104 root.subtitleMoving = true 0105 root.subtitleItem = subtitleClipArea 0106 incrementalOffset = 0 0107 } 0108 if (timeline.selection.indexOf(subtitleRoot.subId) === -1) { 0109 controller.requestAddToSelection(subtitleRoot.subId, !(mouse.modifiers & Qt.ShiftModifier)) 0110 timeline.showAsset(subtitleRoot.subId); 0111 } else if (mouse.modifiers & Qt.ShiftModifier) { 0112 console.log('REMOVE FROM SELECTION!!!!') 0113 controller.requestRemoveFromSelection(subtitleRoot.subId) 0114 } else { 0115 timeline.showAsset(subtitleRoot.subId) 0116 } 0117 timeline.activeTrack = -2 0118 } 0119 function checkOffset(offset) { 0120 if (pressed && !subtitleBase.textEditBegin && startMove) { 0121 incrementalOffset += offset 0122 newStart = Math.max(0, oldStartFrame + (scrollView.contentX + mapToItem(scrollView,mouseX, 0).x + incrementalOffset - oldStartX)/ root.timeScale) 0123 snappedFrame = controller.suggestSubtitleMove(subtitleRoot.subId, newStart, root.consumerPosition, root.snapping) 0124 root.continuousScrolling(scrollView.contentX + mapToItem(scrollView, mouseX, 0).x + incrementalOffset, 0) 0125 } 0126 } 0127 onPositionChanged: { 0128 incrementalOffset = 0 0129 checkOffset(0) 0130 } 0131 onReleased: mouse => { 0132 root.autoScrolling = timeline.autoScroll 0133 root.subtitleMoving = false 0134 root.subtitleItem = undefined 0135 if (subtitleBase.textEditBegin) { 0136 mouse.accepted = false 0137 return 0138 } 0139 if (startMove) { 0140 startMove = false 0141 if (subtitleBase.x < 0) 0142 subtitleBase.x = 0 0143 if (oldStartFrame != snappedFrame) { 0144 console.log("old start frame",oldStartFrame/timeline.scaleFactor, "new frame after shifting ",oldStartFrame/timeline.scaleFactor + delta) 0145 controller.requestSubtitleMove(subtitleRoot.subId, oldStartFrame, false, false); 0146 controller.requestSubtitleMove(subtitleRoot.subId, snappedFrame, true, true, true); 0147 x = snappedFrame * root.timeScale 0148 } 0149 } 0150 console.log('RELEASED DONE\n\n_______________') 0151 } 0152 onClicked: mouse => { 0153 if (mouse.button == Qt.RightButton) { 0154 //console.log('RIGHT BUTTON CLICKED') 0155 root.showSubtitleClipMenu() 0156 } 0157 } 0158 onDoubleClicked: { 0159 subtitleBase.textEditBegin = true 0160 } 0161 Keys.onShortcutOverride: event => { 0162 event.accepted = subtitleRoot.isGrabbed && (event.key === Qt.Key_Left || event.key === Qt.Key_Right || event.key === Qt.Key_Up || event.key === Qt.Key_Down || event.key === Qt.Key_Escape) 0163 } 0164 Keys.onLeftPressed: event => { 0165 var offset = event.modifiers === Qt.ShiftModifier ? timeline.fps() : 1 0166 if (controller.requestSubtitleMove(subtitleRoot.subId, subtitleRoot.startFrame - offset, true, true)) { 0167 timeline.showToolTip(i18n("Position: %1", timeline.simplifiedTC(subtitleRoot.startFrame))); 0168 } 0169 } 0170 Keys.onRightPressed: event => { 0171 var offset = event.modifiers === Qt.ShiftModifier ? timeline.fps() : 1 0172 if (controller.requestSubtitleMove(subtitleRoot.subId, subtitleRoot.startFrame + offset, true, true)) { 0173 timeline.showToolTip(i18n("Position: %1", timeline.simplifiedTC(subtitleRoot.startFrame))); 0174 } 0175 } 0176 /*Keys.onUpPressed: { 0177 controller.requestClipMove(subtitleRoot.subId, controller.getNextTrackId(subtitleRoot.trackId), subtitleRoot.startFrame, true, true, true); 0178 } 0179 Keys.onDownPressed: { 0180 controller.requestClipMove(subtitleRoot.subId, controller.getPreviousTrackId(subtitleRoot.trackId), subtitleRoot.startFrame, true, true, true); 0181 }*/ 0182 Keys.onEscapePressed: { 0183 timeline.grabCurrent() 0184 //focus = false 0185 } 0186 } 0187 Item { 0188 id: subtitleBase 0189 property bool textEditBegin: false 0190 height: subtitleTrack.height 0191 width: duration * root.timeScale // to make width change wrt timeline scale factor 0192 x: startFrame * root.timeScale; 0193 clip: true 0194 TextField { 0195 id: subtitleEdit 0196 font: miniFont 0197 activeFocusOnPress: true 0198 selectByMouse: true 0199 onEditingFinished: { 0200 subtitleEdit.focus = false 0201 parent.textEditBegin = false 0202 if (subtitleRoot.subtitle != subtitleEdit.text) { 0203 subtitleModel.editSubtitle(subtitleRoot.subId, subtitleEdit.text, subtitleRoot.subtitle) 0204 } 0205 } 0206 anchors.fill: parent 0207 //visible: timeScale >= 6 0208 enabled: parent.textEditBegin 0209 opacity: root.subtitlesDisabled ? 0.5 : 1 0210 onEnabledChanged: { 0211 if (enabled) { 0212 selectAll() 0213 focus = true 0214 forceActiveFocus() 0215 } 0216 } 0217 text: subtitleRoot.subtitle 0218 height: subtitleBase.height 0219 width: subtitleBase.width 0220 wrapMode: TextField.WordWrap 0221 horizontalAlignment: displayText == text ? TextInput.AlignHCenter : TextInput.AlignLeft 0222 background: Rectangle { 0223 color: root.subtitlesLocked ? "#ff6666" : enabled ? "#fff" : '#ccccff' 0224 border { 0225 color: subtitleRoot.selected ? root.selectionColor : "#000" 0226 width: subtitleRoot.isGrabbed ? 8 : 2 0227 } 0228 } 0229 color: 'black' 0230 padding: 0 0231 } 0232 } 0233 Item { 0234 // start position resize handle 0235 id: leftstart 0236 width: root.baseUnit / 2 0237 height: subtitleBase.height 0238 anchors.top: subtitleBase.top 0239 anchors.left: subtitleBase.left 0240 visible: true 0241 MouseArea { 0242 // Left resize handle to change start timing 0243 id: startMouseArea 0244 anchors.fill: parent 0245 hoverEnabled: true 0246 enabled: true 0247 visible: root.activeTool === 0 0248 property int newStart: subtitleRoot.startFrame 0249 property int newDuration: subtitleRoot.duration 0250 property int originalDuration: subtitleRoot.duration 0251 property int oldMouseX 0252 property int oldStartFrame: 0 0253 property bool shiftTrim: false 0254 acceptedButtons: Qt.LeftButton 0255 drag.axis: Drag.XAxis 0256 drag.smoothed: false 0257 cursorShape: containsMouse || pressed ? Qt.SizeHorCursor : Qt.ClosedHandCursor; 0258 drag.target: leftstart 0259 onPressed: mouse => { 0260 root.autoScrolling = false 0261 oldMouseX = mouseX 0262 leftstart.anchors.left = undefined 0263 oldStartFrame = subtitleRoot.startFrame // the original start frame of subtitle 0264 originalDuration = subtitleRoot.duration 0265 newDuration = subtitleRoot.duration 0266 trimIn.opacity = 0 0267 shiftTrim = mouse.modifiers & Qt.ShiftModifier 0268 if (!shiftTrim && (controller.isInGroup(subtitleRoot.subId) || controller.hasMultipleSelection())) { 0269 root.groupTrimData = controller.getGroupData(subtitleRoot.subId) 0270 } 0271 } 0272 onPositionChanged: { 0273 if (pressed) { 0274 newDuration = subtitleRoot.endFrame - Math.round(leftstart.x / root.timeScale) 0275 if (newDuration != originalDuration && subtitleBase.x >= 0) { 0276 var frame = controller.requestItemResize(subtitleRoot.subId, newDuration , false, false, root.snapping, shiftTrim); 0277 if (frame > 0) { 0278 newStart = subtitleRoot.endFrame - frame 0279 } 0280 } 0281 } 0282 } 0283 onReleased: { 0284 //console.log('its RELEASED') 0285 root.autoScrolling = timeline.autoScroll 0286 leftstart.anchors.left = subtitleBase.left 0287 if (oldStartFrame != newStart) { 0288 if (shiftTrim || (root.groupTrimData == undefined || root.activeTool === ProjectTool.RippleTool)) { 0289 controller.requestItemResize(subtitleRoot.subId, subtitleRoot.endFrame - oldStartFrame, false, false); 0290 controller.requestItemResize(subtitleRoot.subId, subtitleRoot.endFrame - newStart, false, true, -1, shiftTrim); 0291 } else { 0292 var updatedGroupData = controller.getGroupData(subtitleRoot.subId) 0293 controller.processGroupResize(root.groupTrimData, updatedGroupData, false) 0294 } 0295 } 0296 root.groupTrimData = undefined 0297 } 0298 onEntered: { 0299 if (!pressed) { 0300 trimIn.opacity = 1 0301 timeline.showKeyBinding(i18n("<b>Drag</b> to resize")) 0302 } 0303 } 0304 onExited: { 0305 trimIn.opacity = 0 0306 if (!subtitleClipArea.containsMouse) { 0307 timeline.showKeyBinding() 0308 } 0309 } 0310 0311 Rectangle { 0312 id: trimIn 0313 anchors.left: parent.left 0314 width: 2 0315 height: parent.height 0316 color: 'lawngreen' 0317 opacity: 0 0318 Drag.active: startMouseArea.drag.active 0319 Drag.proposedAction: Qt.MoveAction 0320 //visible: startMouseArea.pressed 0321 } 0322 } 0323 } 0324 0325 Item { 0326 // end position resize handle 0327 id: rightend 0328 width: root.baseUnit / 2 0329 height: subtitleBase.height 0330 //x: subtitleRoot.endFrame * timeScale 0331 anchors.right: subtitleBase.right 0332 anchors.top: subtitleBase.top 0333 //Drag.active: endMouseArea.drag.active 0334 //Drag.proposedAction: Qt.MoveAction 0335 visible: true 0336 MouseArea { 0337 // Right resize handle to change end timing 0338 id: endMouseArea 0339 anchors.fill: parent 0340 hoverEnabled: true 0341 enabled: true 0342 visible: root.activeTool === 0 0343 property bool sizeChanged: false 0344 property int oldMouseX 0345 acceptedButtons: Qt.LeftButton 0346 property int newDuration: subtitleRoot.duration 0347 property int originalDuration 0348 property bool shiftTrim: false 0349 cursorShape: containsMouse || pressed ? Qt.SizeHorCursor : Qt.ClosedHandCursor; 0350 drag.target: rightend 0351 drag.axis: Drag.XAxis 0352 drag.smoothed: false 0353 0354 onPressed: mouse => { 0355 root.autoScrolling = false 0356 newDuration = subtitleRoot.duration 0357 originalDuration = subtitleRoot.duration 0358 //rightend.anchors.right = undefined 0359 oldMouseX = mouseX 0360 trimOut.opacity = 0 0361 shiftTrim = mouse.modifiers & Qt.ShiftModifier 0362 if (!shiftTrim && (controller.isInGroup(subtitleRoot.subId) || controller.hasMultipleSelection())) { 0363 root.groupTrimData = controller.getGroupData(subtitleRoot.subId) 0364 } 0365 } 0366 onPositionChanged: { 0367 if (pressed) { 0368 if ((mouseX != oldMouseX && duration > 1) || (duration <= 1 && mouseX > oldMouseX)) { 0369 sizeChanged = true 0370 //duration = subtitleBase.width + (mouseX - oldMouseX)/ timeline.scaleFactor 0371 newDuration = Math.round((subtitleBase.width + mouseX - oldMouseX)/timeScale) 0372 // Perform resize without changing model 0373 var frame = controller.requestItemResize(subtitleRoot.subId, newDuration , true, false, root.snapping, shiftTrim); 0374 if (frame > 0) { 0375 newDuration = frame 0376 } 0377 } 0378 } 0379 } 0380 onReleased: { 0381 root.autoScrolling = timeline.autoScroll 0382 rightend.anchors.right = subtitleBase.right 0383 console.log(' GOT RESIZE: ', newDuration, ' > ', originalDuration) 0384 if (mouseX != oldMouseX || sizeChanged) { 0385 if (shiftTrim || (root.groupTrimData == undefined || root.activeTool === ProjectTool.RippleTool)) { 0386 // Restore original size 0387 controller.requestItemResize(subtitleRoot.subId, originalDuration , true, false); 0388 // Perform real resize 0389 controller.requestItemResize(subtitleRoot.subId, newDuration , true, true, -1, shiftTrim) 0390 } else { 0391 var updatedGroupData = controller.getGroupData(subtitleRoot.subId) 0392 controller.processGroupResize(root.groupTrimData, updatedGroupData, true) 0393 } 0394 sizeChanged = false 0395 } 0396 root.groupTrimData = undefined 0397 } 0398 onEntered: { 0399 console.log('ENTER MOUSE END AREA') 0400 if (!pressed) { 0401 trimOut.opacity = 1 0402 timeline.showKeyBinding(i18n("<b>Drag</b> to resize")) 0403 } 0404 } 0405 onExited: { 0406 trimOut.opacity = 0 0407 if (!subtitleClipArea.containsMouse) { 0408 timeline.showKeyBinding() 0409 } 0410 } 0411 0412 Rectangle { 0413 id: trimOut 0414 anchors.right: parent.right 0415 width: 2 0416 height: parent.height 0417 color: 'red' 0418 opacity: 0 0419 Drag.active: endMouseArea.drag.active 0420 Drag.proposedAction: Qt.MoveAction 0421 //visible: endMouseArea.pressed 0422 } 0423 } 0424 } 0425 }