Warning, /multimedia/kdenlive/src/timeline2/view/qml/TrackHead.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-FileCopyrightText: 2013-2016 Meltytech LLC 0003 SPDX-FileCopyrightText: 2013-2016 Dan Dennedy <dan@dennedy.org> 0004 0005 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0006 */ 0007 0008 import QtQuick 2.15 0009 import QtQuick.Controls 2.15 0010 0011 Rectangle { 0012 id: trackHeadRoot 0013 property string trackName 0014 property string effectNames 0015 property bool isStackEnabled 0016 property bool isDisabled 0017 property bool collapsed: false 0018 property int isComposite 0019 property bool isLocked: false 0020 property bool isActive: false 0021 property bool isAudio 0022 property bool showAudioRecord: false 0023 property bool current: false 0024 property int trackId : -42 0025 property string trackTag 0026 property int thumbsFormat: 0 0027 border.width: 1 0028 border.color: root.frameColor 0029 0030 function editName() { 0031 nameEdit.visible = true 0032 nameEdit.focus = true 0033 nameEdit.selectAll() 0034 } 0035 0036 function animateLock() { 0037 flashLock.restart(); 0038 } 0039 0040 onShowAudioRecordChanged: { 0041 if (showAudioRecord && trackHeadRoot.height < 2 * root.collapsedHeight + resizer.height) { 0042 // Ensure trackheight is large enough to have the vu-meter visible 0043 timeline.adjustTrackHeight(trackHeadRoot.trackId, 2 * root.collapsedHeight + resizer.height) 0044 } 0045 } 0046 0047 color: getTrackColor(isAudio, true) 0048 //border.color: selected? 'red' : 'transparent' 0049 //border.width: selected? 1 : 0 0050 clip: true 0051 state: 'normal' 0052 states: [ 0053 State { 0054 name: 'current' 0055 when: trackHeadRoot.current 0056 PropertyChanges { 0057 target: trackHeadRoot 0058 color: showAudioRecord ? Qt.tint(selectedTrackColor, Qt.rgba(1, 0, 0, 0.5)) : selectedTrackColor 0059 } 0060 }, 0061 State { 0062 when: !trackHeadRoot.current 0063 name: 'normal' 0064 PropertyChanges { 0065 target: trackHeadRoot 0066 color: showAudioRecord ? Qt.tint(getTrackColor(isAudio, true), Qt.rgba(1, 0, 0, 0.16)) : getTrackColor(isAudio, true) 0067 } 0068 } 0069 ] 0070 0071 Keys.onDownPressed: { 0072 root.moveSelectedTrack(1) 0073 } 0074 Keys.onUpPressed: { 0075 root.moveSelectedTrack(-1) 0076 } 0077 0078 MouseArea { 0079 id: headerMouseArea 0080 anchors.fill: parent 0081 hoverEnabled: true 0082 acceptedButtons: Qt.LeftButton | Qt.RightButton 0083 onPressed: mouse => { 0084 timeline.activeTrack = trackId 0085 if (mouse.button == Qt.RightButton) { 0086 root.showHeaderMenu() 0087 } 0088 } 0089 onClicked: mouse => { 0090 console.log('TRACK ID: ', trackId) 0091 parent.forceActiveFocus() 0092 nameEdit.visible = false 0093 if (mouse.button == Qt.LeftButton) { 0094 timeline.showTrackAsset(trackId) 0095 } 0096 } 0097 } 0098 Label { 0099 id: trackTarget 0100 property color bgColor: 'grey' 0101 font: miniFont 0102 color: timeline.targetTextColor 0103 background: Rectangle { 0104 color: trackTarget.bgColor 0105 } 0106 width: 1.5 * root.baseUnit 0107 height: trackHeadRoot.height 0108 verticalAlignment: Text.AlignTop 0109 horizontalAlignment: Text.AlignHCenter 0110 visible: trackHeadRoot.isAudio ? timeline.hasAudioTarget > 0 : timeline.hasVideoTarget 0111 anchors.top: parent.top 0112 anchors.bottom: parent.bottom 0113 anchors.margins: 1 0114 0115 MouseArea { 0116 id: targetArea 0117 anchors.fill: parent 0118 hoverEnabled: true 0119 acceptedButtons: Qt.LeftButton | Qt.RightButton 0120 cursorShape: Qt.PointingHandCursor 0121 onClicked: mouse => { 0122 if (mouse.button == Qt.RightButton) { 0123 if (trackHeadRoot.isAudio) { 0124 root.showTargetMenu(trackId) 0125 } else { 0126 root.showHeaderMenu() 0127 } 0128 } 0129 else { 0130 if (trackHeadRoot.isAudio) { 0131 timeline.switchAudioTarget(trackHeadRoot.trackId); 0132 } else { 0133 if (trackHeadRoot.trackId === timeline.videoTarget) { 0134 timeline.videoTarget = -1; 0135 } else if (timeline.hasVideoTarget) { 0136 timeline.videoTarget = trackHeadRoot.trackId; 0137 } 0138 } 0139 } 0140 } 0141 ToolButton { 0142 id: targetMouse 0143 focusPolicy: Qt.NoFocus 0144 visible: trackHeadRoot.isAudio && timeline.clipTargets > 1 && trackHeadRoot.height > (2 * expandButton.height) 0145 background: Rectangle { 0146 color: Qt.darker(trackTarget.bgColor, 1.5) 0147 border.color: activePalette.light 0148 } 0149 anchors.bottom: parent.bottom 0150 width: parent.width 0151 height: width 0152 contentItem: Item { 0153 Image { 0154 source: "image://icon/go-down" 0155 anchors.fill: parent 0156 } 0157 } 0158 onClicked: { 0159 root.showTargetMenu(trackId) 0160 } 0161 ToolTip { 0162 visible: targetMouse.hovered 0163 font: miniFont 0164 delay: 1500 0165 timeout: 5000 0166 background: Rectangle { 0167 color: activePalette.alternateBase 0168 border.color: activePalette.light 0169 } 0170 contentItem: Label { 0171 color: activePalette.text 0172 text: timeline.actionText("switch_target_stream") 0173 } 0174 } 0175 } 0176 } 0177 ToolTip { 0178 visible: targetArea.containsMouse && !targetMouse.hovered 0179 font: miniFont 0180 delay: 1500 0181 timeout: 5000 0182 background: Rectangle { 0183 color: activePalette.alternateBase 0184 border.color: activePalette.light 0185 } 0186 contentItem: Label { 0187 color: activePalette.text 0188 text: i18n("Click to toggle track as target. Target tracks will receive the inserted clips") 0189 } 0190 } 0191 state: 'normalTarget' 0192 states: [ 0193 State { 0194 name: 'target' 0195 when: (trackHeadRoot.isAudio && timeline.audioTarget.indexOf(trackHeadRoot.trackId) > -1) || (!trackHeadRoot.isAudio && trackHeadRoot.trackId === timeline.videoTarget) 0196 PropertyChanges { 0197 target: trackTarget 0198 bgColor: timeline.targetColor 0199 text: trackHeadRoot.isAudio ? timeline.audioTargetName(trackHeadRoot.trackId) : '' 0200 } 0201 }, 0202 State { 0203 name: 'inactiveTarget' 0204 when: (trackHeadRoot.isAudio && timeline.lastAudioTarget.indexOf(trackHeadRoot.trackId) > -1) || (!trackHeadRoot.isAudio && trackHeadRoot.trackId == timeline.lastVideoTarget) 0205 PropertyChanges { 0206 target: trackTarget 0207 opacity: 0.3 0208 bgColor: activePalette.text 0209 text: trackHeadRoot.isAudio ? timeline.audioTargetName(trackHeadRoot.trackId) : '' 0210 } 0211 }, 0212 State { 0213 name: 'noTarget' 0214 when: !trackHeadRoot.isLocked && !trackHeadRoot.isDisabled 0215 PropertyChanges { 0216 target: trackTarget 0217 bgColor: activePalette.base 0218 text: '' 0219 } 0220 } 0221 ] 0222 transitions: [ 0223 Transition { 0224 to: '*' 0225 ColorAnimation { target: trackTarget; duration: 300 } 0226 } 0227 ] 0228 } 0229 Item { 0230 id: trackHeadColumn 0231 anchors.fill: parent 0232 anchors.leftMargin: trackTarget.width 0233 anchors.topMargin: 0 0234 0235 ToolButton { 0236 id: expandButton 0237 focusPolicy: Qt.NoFocus 0238 property var modifier: 0 0239 contentItem: Item { 0240 Image { 0241 source: trackHeadRoot.collapsed ? "image://icon/go-next" : "image://icon/go-down" 0242 anchors.centerIn: parent 0243 width: root.collapsedHeight - 4 0244 height: width 0245 cache: root.paletteUnchanged 0246 } 0247 } 0248 onClicked: { 0249 if (modifier & Qt.ShiftModifier) { 0250 // Collapse / expand all tracks 0251 timeline.collapseAllTrackHeight(trackId, !trackHeadRoot.collapsed, root.collapsedHeight) 0252 } else { 0253 if (trackHeadRoot.collapsed) { 0254 var newHeight = Math.max(root.collapsedHeight * 1.5, controller.getTrackProperty(trackId, "kdenlive:trackheight")) 0255 controller.setTrackProperty(trackId, "kdenlive:trackheight", newHeight) 0256 controller.setTrackProperty(trackId, "kdenlive:collapsed", "0") 0257 } else { 0258 controller.setTrackProperty(trackId, "kdenlive:collapsed", root.collapsedHeight) 0259 } 0260 } 0261 if (root.autoTrackHeight) { 0262 timeline.autofitTrackHeight(scrollView.height - subtitleTrack.height, root.collapsedHeight) 0263 } 0264 } 0265 MouseArea { 0266 // Used to pass modifier state to expand button 0267 anchors.fill: parent 0268 acceptedButtons: Qt.LeftButton 0269 hoverEnabled: true 0270 onPressed: mouse => { 0271 expandButton.modifier = mouse.modifiers 0272 mouse.accepted = false 0273 } 0274 onEntered: { 0275 timeline.showKeyBinding(i18n("<b>Shift</b> to collapse/expand all tracks of the same type (audio/video)")) 0276 } 0277 onExited: { 0278 timeline.showKeyBinding() 0279 } 0280 } 0281 anchors.left: parent.left 0282 width: root.collapsedHeight 0283 height: root.collapsedHeight 0284 ToolTip { 0285 visible: expandButton.hovered 0286 font: miniFont 0287 delay: 1500 0288 timeout: 5000 0289 background: Rectangle { 0290 color: activePalette.alternateBase 0291 border.color: activePalette.light 0292 } 0293 contentItem: Label { 0294 color: activePalette.text 0295 text: trackLabel.visible? i18n("Minimize") : i18n("Expand") 0296 } 0297 } 0298 } 0299 Label { 0300 id: trackLed 0301 property color bgColor: Qt.darker(trackHeadRoot.color, 0.55) 0302 anchors.left: expandButton.right 0303 font: miniFont 0304 text: trackHeadRoot.trackTag 0305 color: activePalette.text 0306 background: Rectangle { 0307 color: trackLed.bgColor 0308 } 0309 width: root.trackTagWidth 0310 height: root.collapsedHeight - 2 0311 y: 1 0312 verticalAlignment: Text.AlignVCenter 0313 horizontalAlignment: Text.AlignHCenter 0314 MouseArea { 0315 id: tagMouseArea 0316 anchors.fill: parent 0317 hoverEnabled: true 0318 cursorShape: Qt.PointingHandCursor 0319 onClicked: { 0320 timeline.switchTrackActive(trackHeadRoot.trackId) 0321 } 0322 } 0323 ToolTip { 0324 visible: tagMouseArea.containsMouse 0325 font: miniFont 0326 delay: 1500 0327 timeout: 5000 0328 background: Rectangle { 0329 color: activePalette.alternateBase 0330 border.color: activePalette.light 0331 } 0332 contentItem: Label { 0333 color: activePalette.text 0334 text: i18n("Click to make track active/inactive. Active tracks will react to editing operations") 0335 } 0336 } 0337 state: 'normalled' 0338 states: [ 0339 State { 0340 name: 'locked' 0341 when: trackHeadRoot.isLocked 0342 PropertyChanges { 0343 target: trackLed 0344 bgColor: 'red' 0345 } 0346 }, 0347 State { 0348 name: 'active' 0349 when: trackHeadRoot.isActive 0350 PropertyChanges { 0351 target: trackLed 0352 bgColor: timeline.targetColor 0353 color: timeline.targetTextColor 0354 } 0355 }, 0356 State { 0357 name: 'inactive' 0358 when: !trackHeadRoot.isLocked && !trackHeadRoot.isActive 0359 PropertyChanges { 0360 target: trackLed 0361 bgColor: Qt.darker(trackHeadRoot.color, 0.55) 0362 } 0363 } 0364 ] 0365 transitions: [ 0366 Transition { 0367 to: '*' 0368 ColorAnimation { target: trackLed; duration: 300 } 0369 } 0370 ] 0371 } 0372 Label { 0373 // Debug: trackId 0374 anchors.left: trackLed.right 0375 background: Rectangle { 0376 color: 'magenta' 0377 } 0378 anchors.leftMargin: 2 0379 width: root.trackTagWidth * 2 0380 height: root.collapsedHeight - 2 0381 y: 1 0382 text: trackHeadRoot.trackId 0383 elide: Text.ElideRight 0384 font: miniFont 0385 verticalAlignment: Text.AlignVCenter 0386 horizontalAlignment: Text.AlignHCenter 0387 visible: root.debugmode 0388 } 0389 Label { 0390 anchors.left: trackLed.right 0391 anchors.top: parent.top 0392 anchors.leftMargin: 2 0393 height: trackLed.height 0394 width: buttonsRow.x - x 0395 text: trackHeadRoot.trackName 0396 elide: Text.ElideRight 0397 font: miniFont 0398 verticalAlignment: Text.AlignVCenter 0399 horizontalAlignment: Text.AlignLeft 0400 visible: !trackLabel.visible && trackHeadRoot.width > (trackTarget.width + expandButton.width + trackLed.width + (4 * muteButton.width) + 4) 0401 } 0402 Row { 0403 id: buttonsRow 0404 width: childrenRect.width 0405 x: Math.max(2 * root.collapsedHeight + 2, parent.width - width - 4) 0406 spacing: 0 0407 ToolButton { 0408 id: effectButton 0409 focusPolicy: Qt.NoFocus 0410 contentItem: Item { 0411 Image { 0412 source: "image://icon/tools-wizard" 0413 anchors.centerIn: parent 0414 width: root.collapsedHeight - 4 0415 height: width 0416 cache: root.paletteUnchanged 0417 opacity: effectButton.enabled ? 1 : 0.5 0418 } 0419 } 0420 enabled: trackHeadRoot.effectNames != '' 0421 checkable: true 0422 checked: enabled && trackHeadRoot.isStackEnabled 0423 onClicked: { 0424 timeline.showTrackAsset(trackId) 0425 controller.setTrackStackEnabled(trackId, !isStackEnabled) 0426 } 0427 width: root.collapsedHeight 0428 height: root.collapsedHeight 0429 ToolTip { 0430 visible: effectButton.hovered 0431 font: miniFont 0432 delay: 1500 0433 timeout: 5000 0434 background: Rectangle { 0435 color: activePalette.alternateBase 0436 border.color: activePalette.light 0437 } 0438 contentItem: Label { 0439 color: activePalette.text 0440 text: enabled ? (isStackEnabled ? i18n("Disable track effects") : i18n("Enable track effects")) : i18n("Toggle track effects"); 0441 } 0442 } 0443 } 0444 ToolButton { 0445 id: muteButton 0446 focusPolicy: Qt.NoFocus 0447 contentItem: Item { 0448 Image { 0449 source: isAudio ? (isDisabled ? "image://icon/kdenlive-hide-audio" : "image://icon/kdenlive-show-audio") : (isDisabled ? "image://icon/kdenlive-hide-video" : "image://icon/kdenlive-show-video") 0450 anchors.centerIn: parent 0451 width: root.collapsedHeight - 4 0452 height: width 0453 cache: root.paletteUnchanged 0454 } 0455 } 0456 width: root.collapsedHeight 0457 height: root.collapsedHeight 0458 onClicked: timeline.hideTrack(trackId, isDisabled) 0459 ToolTip { 0460 visible: muteButton.hovered 0461 font: miniFont 0462 delay: 1500 0463 timeout: 5000 0464 background: Rectangle { 0465 color: activePalette.alternateBase 0466 border.color: activePalette.light 0467 } 0468 contentItem: Label { 0469 color: activePalette.text 0470 text: isAudio ? (isDisabled? i18n("Unmute") : i18n("Mute")) : (isDisabled? i18n("Show") : i18n("Hide")) 0471 } 0472 } 0473 } 0474 0475 ToolButton { 0476 id: lockButton 0477 width: root.collapsedHeight 0478 height: root.collapsedHeight 0479 focusPolicy: Qt.NoFocus 0480 contentItem: Rectangle { 0481 id: bgRect 0482 color: 'transparent' 0483 anchors.fill: parent 0484 Image { 0485 source: trackHeadRoot.isLocked ? "image://icon/lock" : "image://icon/unlock" 0486 anchors.centerIn: parent 0487 width: root.collapsedHeight - 4 0488 height: width 0489 cache: root.paletteUnchanged 0490 } 0491 } 0492 onClicked: controller.setTrackLockedState(trackId, !isLocked) 0493 ToolTip { 0494 visible: lockButton.hovered 0495 font: miniFont 0496 delay: 1500 0497 timeout: 5000 0498 background: Rectangle { 0499 color: activePalette.alternateBase 0500 border.color: activePalette.light 0501 } 0502 contentItem: Label { 0503 color: activePalette.text 0504 text: isLocked? i18n("Unlock track") : i18n("Lock track") 0505 } 0506 } 0507 SequentialAnimation { 0508 id: flashLock 0509 loops: 3 0510 ParallelAnimation { 0511 ScaleAnimator {target: lockButton; from: 1; to: 1.2; duration: 120} 0512 PropertyAnimation {target: bgRect;property: "color"; from: "transparent"; to: "darkred"; duration: 100} 0513 } 0514 ParallelAnimation { 0515 ScaleAnimator {target: lockButton; from: 1.6; to: 1; duration: 120} 0516 PropertyAnimation {target: bgRect;property: "color"; from: "darkred"; to: "transparent"; duration: 120} 0517 } 0518 } 0519 } 0520 } 0521 Item { 0522 id: recLayout 0523 y: root.collapsedHeight + 4 0524 anchors.left: trackHeadColumn.left 0525 anchors.right: trackHeadColumn.right 0526 anchors.margins: 2 0527 height: showAudioRecord ? root.collapsedHeight - 4 : 0 0528 Loader { 0529 id: audioVuMeter 0530 asynchronous: true 0531 anchors.fill: parent 0532 visible: showAudioRecord && (trackHeadRoot.height >= 2 * root.collapsedHeight + resizer.height) 0533 source: isAudio && showAudioRecord ? "AudioLevels.qml" : "" 0534 onLoaded: item.trackId = trackId 0535 } 0536 } 0537 Item { 0538 anchors.bottom: trackHeadColumn.bottom 0539 anchors.left: trackHeadColumn.left 0540 anchors.right: trackHeadColumn.right 0541 anchors.margins: 2 0542 height: nameEdit.height 0543 Rectangle { 0544 id: trackLabel 0545 color: 'transparent' 0546 radius: 2 0547 anchors.fill: parent 0548 border.color: trackNameMouseArea.containsMouse ? activePalette.highlight : 'transparent' 0549 visible: (trackHeadRoot.height >= trackLabel.height + muteButton.height + resizer.height + recLayout.height) 0550 MouseArea { 0551 id: trackNameMouseArea 0552 anchors.fill: parent 0553 hoverEnabled: true 0554 propagateComposedEvents: true 0555 cursorShape: Qt.IBeamCursor 0556 onDoubleClicked: editName() 0557 onClicked: { 0558 timeline.showTrackAsset(trackId) 0559 timeline.activeTrack = trackId 0560 trackHeadRoot.focus = true 0561 } 0562 } 0563 Label { 0564 text: trackName 0565 anchors.verticalCenter: parent.verticalCenter 0566 anchors.left: parent.left 0567 anchors.leftMargin: 4 0568 elide: Qt.ElideRight 0569 font: miniFont 0570 } 0571 Label { 0572 id: placeHolder 0573 visible: trackName == '' && (trackNameMouseArea.containsMouse || headerMouseArea.containsMouse) 0574 enabled: false 0575 text: i18n("Edit track name") 0576 anchors.verticalCenter: parent.verticalCenter 0577 anchors.left: parent.left 0578 anchors.leftMargin: 4 0579 elide: Qt.ElideRight 0580 font: miniFont 0581 } 0582 TextField { 0583 id: nameEdit 0584 visible: false 0585 width: parent.width 0586 text: trackName 0587 font: miniFont 0588 background: Rectangle { 0589 radius: 2 0590 color: activePalette.window 0591 anchors.fill: parent 0592 } 0593 /*style: TextFieldStyle { 0594 padding.top:0 0595 padding.bottom: 0 0596 background: Rectangle { 0597 radius: 2 0598 color: activePalette.window 0599 anchors.fill: parent 0600 } 0601 }*/ 0602 onEditingFinished: { 0603 controller.setTrackName(trackId, text) 0604 tracksArea.focus = true 0605 visible = false 0606 } 0607 } 0608 } 0609 } 0610 } 0611 Rectangle { 0612 id: resizer 0613 height: Math.round(root.baseUnit/3) 0614 color: 'red' 0615 opacity: 0 0616 Drag.active: trimInMouseArea.drag.active 0617 Drag.proposedAction: Qt.MoveAction 0618 width: trackHeadRoot.width 0619 y: trackHeadRoot.height - height 0620 0621 MouseArea { 0622 id: trimInMouseArea 0623 anchors.fill: parent 0624 hoverEnabled: true 0625 cursorShape: Qt.SizeVerCursor 0626 drag.target: parent 0627 drag.axis: Drag.YAxis 0628 drag.minimumY: root.collapsedHeight - resizer.height 0629 property double startY 0630 property double originalY 0631 drag.smoothed: false 0632 property bool dragStarted: false 0633 0634 onPressed: { 0635 root.autoScrolling = false 0636 dragStarted = false 0637 startY = mapToItem(null, x, y).y 0638 originalY = trackHeadRoot.height // reusing originalX to accumulate delta for bubble help 0639 } 0640 onReleased: mouse => { 0641 root.autoScrolling = timeline.autoScroll 0642 if (!trimInMouseArea.containsMouse) { 0643 parent.opacity = 0 0644 } 0645 if (mouse.modifiers & Qt.ShiftModifier && dragStarted) { 0646 timeline.adjustAllTrackHeight(trackHeadRoot.trackId, trackHeadRoot.height) 0647 } 0648 } 0649 onEntered: parent.opacity = 0.3 0650 onExited: parent.opacity = 0 0651 onDoubleClicked: mouse => { 0652 timeline.defaultTrackHeight(mouse.modifiers & Qt.ShiftModifier ? -1 : trackHeadRoot.trackId) 0653 } 0654 onPositionChanged: mouse=> { 0655 if (mouse.buttons === Qt.LeftButton) { 0656 parent.opacity = 0.5 0657 if (!dragStarted && Math.abs(mapToItem(null, x, y).y - startY) > 2) { 0658 dragStarted = true 0659 } 0660 var newHeight = originalY + (mapToItem(null, x, y).y - startY) 0661 newHeight = Math.max(root.collapsedHeight, newHeight) 0662 if (newHeight == root.collapsedHeight) { 0663 controller.setTrackProperty(trackId, "kdenlive:collapsed", root.collapsedHeight) 0664 } else { 0665 controller.setTrackProperty(trackId, "kdenlive:trackheight", newHeight) 0666 controller.setTrackProperty(trackId, "kdenlive:collapsed", "0") 0667 } 0668 } 0669 } 0670 } 0671 } 0672 DropArea { //Drop area for tracks 0673 anchors.fill: trackHeadRoot 0674 keys: 'kdenlive/effect' 0675 property string dropData 0676 property string dropSource 0677 property int dropRow: -1 0678 onEntered: drag => { 0679 dropData = drag.getDataAsString('kdenlive/effect') 0680 dropSource = drag.getDataAsString('kdenlive/effectsource') 0681 } 0682 onDropped: drag => { 0683 console.log("Add effect: ", dropData) 0684 if (dropSource == '') { 0685 // drop from effects list 0686 controller.addTrackEffect(trackHeadRoot.trackId, dropData); 0687 } else { 0688 controller.copyTrackEffect(trackHeadRoot.trackId, dropSource); 0689 } 0690 dropSource = '' 0691 dropRow = -1 0692 drag.acceptProposedAction 0693 } 0694 } 0695 } 0696