Warning, /multimedia/kdenlive/src/monitor/view/kdenliveclipmonitor.qml is written in an unsupported language. File is not indexed.
0001 /*
0002 SPDX-FileCopyrightText: 2015 Jean-Baptiste Mardelle <jb@kdenlive.org>
0003 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005
0006 import QtQuick.Controls 2.15
0007 import QtQuick.Window 2.15
0008 import Kdenlive.Controls 1.0
0009 import QtQuick 2.15
0010 import com.enums 1.0
0011
0012 Item {
0013 id: root
0014 objectName: "root"
0015
0016 SystemPalette { id: activePalette }
0017
0018 // default size, but scalable by user
0019 height: 300; width: 400
0020 property string markerText
0021 property int itemType: 0
0022 property point profile: controller.profile
0023 property double zoom
0024 property point center
0025 property double scalex
0026 property double scaley
0027 property bool captureRightClick: false
0028 // Zoombar properties
0029 // The start position of the zoomed area, between 0 and 1
0030 property double zoomStart: 0
0031 // The zoom factor (between 0 and 1). 0.5 means 2x zoom
0032 property double zoomFactor: 1
0033 // The pixel height of zoom bar, used to offset markers info
0034 property int zoomOffset: 0
0035 property bool showZoomBar: false
0036 property double offsetx : 0
0037 property double offsety : 0
0038 property bool dropped: false
0039 property string fps: '-'
0040 property bool showMarkers: false
0041 property bool showTimecode: false
0042 property bool showFps: false
0043 property bool showSafezone: false
0044 // Display hover audio thumbnails overlay
0045 property bool showAudiothumb: false
0046 property bool showClipJobs: false
0047 // Always display audio thumbs under video
0048 property bool permanentAudiothumb: false
0049 property bool showToolbar: false
0050 property string clipName: controller.clipName
0051 property real baseUnit: fontMetrics.font.pixelSize * 0.8
0052 property int duration: 300
0053 property int mouseRulerPos: 0
0054 property double frameSize: 10
0055 property double timeScale: 1
0056 property int overlayType: controller.overlayType
0057 property color thumbColor1: controller.thumbColor1
0058 property color thumbColor2: controller.thumbColor2
0059 property color overlayColor: controller.overlayColor
0060 property bool isClipMonitor: true
0061 property int dragType: 0
0062 property string baseThumbPath
0063 property int overlayMargin: (audioThumb.stateVisible && !audioThumb.isAudioClip && audioThumb.visible) ? (audioThumb.height + root.zoomOffset) : root.zoomOffset + (audioThumb.isAudioClip && audioSeekZone.visible) ? audioSeekZone.height : 0
0064
0065 function updateClickCapture() {
0066 root.captureRightClick = false
0067 }
0068
0069 FontMetrics {
0070 id: fontMetrics
0071 font: fixedFont
0072 }
0073
0074 Timer {
0075 id: thumbTimer
0076 interval: 3000; running: false;
0077 }
0078
0079 signal editCurrentMarker()
0080 signal endDrag()
0081
0082 function updateScrolling()
0083 {
0084 if (thumbMouseArea.pressed) {
0085 var pos = Math.max(thumbMouseArea.mouseX, 0)
0086 pos += audioThumb.width/root.zoomFactor * root.zoomStart
0087 controller.setPosition(Math.min(pos / root.timeScale, root.duration));
0088
0089 }
0090 }
0091
0092 onDurationChanged: {
0093 clipMonitorRuler.updateRuler()
0094 }
0095 onWidthChanged: {
0096 clipMonitorRuler.updateRuler()
0097 }
0098 onClipNameChanged: {
0099 // Animate clip name
0100 labelContainer.opacity = 1
0101 contextMenu.opacity = 1
0102 if (!clipNameLabel.hovered) {
0103 showAnimate.restart()
0104 }
0105
0106 // adjust monitor image size if audio thumb is displayed
0107 if (audioThumb.stateVisible && root.permanentAudiothumb && audioThumb.visible) {
0108 controller.rulerHeight = audioThumb.height + root.zoomOffset
0109 } else {
0110 controller.rulerHeight = root.zoomOffset
0111 }
0112 }
0113
0114 onZoomOffsetChanged: {
0115 if (audioThumb.stateVisible && root.permanentAudiothumb && audioThumb.visible) {
0116 controller.rulerHeight = audioThumb.height + root.zoomOffset
0117 } else {
0118 controller.rulerHeight = root.zoomOffset
0119 }
0120 }
0121
0122 onHeightChanged: {
0123 if (audioThumb.stateVisible && root.permanentAudiothumb && audioThumb.visible) {
0124 controller.rulerHeight = (audioThumb.isAudioClip ? (root.height - controller.rulerHeight) : (root.height - controller.rulerHeight)/ 6) + root.zoomOffset
0125 } else {
0126 controller.rulerHeight = root.zoomOffset
0127 }
0128 }
0129
0130 function updatePalette() {
0131 clipMonitorRuler.forceRepaint()
0132 }
0133
0134 function switchOverlay() {
0135 if (controller.overlayType >= 5) {
0136 controller.overlayType = 0
0137 } else {
0138 controller.overlayType = controller.overlayType + 1;
0139 }
0140 root.overlayType = controller.overlayType
0141 }
0142
0143 MouseArea {
0144 id: barOverArea
0145 hoverEnabled: true
0146 // Enable to block hide menu event
0147 acceptedButtons: contextMenu.visible ? Qt.LeftButton : Qt.NoButton
0148 anchors.fill: parent
0149 onPositionChanged: mouse => {
0150 if (mouse.modifiers & Qt.ShiftModifier) {
0151 var pos = Math.max(mouseX, 0)
0152 pos += width/root.zoomFactor * root.zoomStart
0153 controller.setPosition(Math.min(pos / root.timeScale, root.duration));
0154 }
0155 }
0156 onWheel: wheel => {
0157 controller.seek(wheel.angleDelta.x + wheel.angleDelta.y, wheel.modifiers)
0158 }
0159 onEntered: {
0160 // Show clip name
0161 labelContainer.opacity = 1
0162 contextMenu.opacity = 1
0163 if (!clipNameLabel.hovered) {
0164 showAnimate.restart()
0165 }
0166 controller.setWidgetKeyBinding(xi18nc("@info:whatsthis", "<shortcut>Click</shortcut> to play, <shortcut>Double click</shortcut> for fullscreen, <shortcut>Hover right</shortcut> for toolbar, <shortcut>Wheel</shortcut> or <shortcut>arrows</shortcut> to seek, <shortcut>Ctrl wheel</shortcut> to zoom"));
0167 }
0168 onExited: {
0169 controller.setWidgetKeyBinding();
0170 }
0171 }
0172
0173 SceneToolBar {
0174 id: sceneToolBar
0175 anchors {
0176 right: parent.right
0177 top: parent.top
0178 topMargin: 4
0179 rightMargin: 4
0180 leftMargin: 4
0181 }
0182 }
0183
0184 Item {
0185 height: root.height - controller.rulerHeight
0186 width: root.width
0187 Item {
0188 id: frame
0189 objectName: "referenceframe"
0190 width: root.profile.x * root.scalex
0191 height: root.profile.y * root.scaley
0192 x: root.center.x - width / 2 - root.offsetx;
0193 y: root.center.y - height / 2 - root.offsety;
0194
0195 Loader {
0196 anchors.fill: parent
0197 source: {
0198 switch(root.overlayType)
0199 {
0200 case 0:
0201 return '';
0202 case 1:
0203 return "OverlayStandard.qml";
0204 case 2:
0205 return "OverlayMinimal.qml";
0206 case 3:
0207 return "OverlayCenter.qml";
0208 case 4:
0209 return "OverlayCenterDiagonal.qml";
0210 case 5:
0211 return "OverlayThirds.qml";
0212 }
0213 }
0214 }
0215 }
0216 DropArea { //Drop area for effects
0217 id: effectArea
0218 anchors.fill: parent
0219 keys: 'kdenlive/effect'
0220 property string droppedData
0221 property string droppedDataSource
0222 onEntered: drag => {
0223 drag.acceptProposedAction()
0224 droppedData = drag.getDataAsString('kdenlive/effect')
0225 droppedDataSource = drag.getDataAsString('kdenlive/effectsource')
0226 }
0227 onDropped: {
0228 controller.addEffect(droppedData, droppedDataSource)
0229 droppedData = ""
0230 droppedDataSource = ""
0231 }
0232 }
0233 Item {
0234 id: monitorOverlay
0235 anchors.fill: parent
0236
0237 Item {
0238 id: audioThumb
0239 property bool stateVisible: (root.permanentAudiothumb || clipMonitorRuler.containsMouse || thumbMouseArea.containsMouse || dragZone.opacity == 1 || thumbTimer.running || root.showZoomBar)
0240 property bool isAudioClip: controller.clipType == ProducerType.Audio
0241 anchors {
0242 left: parent.left
0243 bottom: parent.bottom
0244 bottomMargin: root.zoomOffset
0245 }
0246 height: isAudioClip ? parent.height : parent.height / 6
0247 //font.pixelSize * 3
0248 width: parent.width
0249 visible: (root.permanentAudiothumb || root.showAudiothumb) && (isAudioClip || controller.clipType == ProducerType.AV || controller.clipHasAV)
0250 Label {
0251 id: clipStreamLabel
0252 font: fixedFont
0253 anchors {
0254 bottom: audioThumb.isAudioClip ? parent.bottom : parent.top
0255 horizontalCenter: parent.horizontalCenter
0256 }
0257 color: "white"
0258 text: controller.clipStream
0259 background: Rectangle {
0260 color: "#222277"
0261 }
0262 visible: text != ""
0263 padding :4
0264 }
0265 onStateVisibleChanged: {
0266 // adjust monitor image size
0267 if (stateVisible && root.permanentAudiothumb && audioThumb.visible) {
0268 controller.rulerHeight = audioThumb.height + root.zoomOffset
0269 } else {
0270 controller.rulerHeight = root.zoomOffset
0271 }
0272 }
0273
0274 states: [
0275 State { when: audioThumb.stateVisible || audioThumb.isAudioClip;
0276 PropertyChanges { target: audioThumb; opacity: 1.0 } },
0277 State { when: !audioThumb.stateVisible && !audioThumb.isAudioClip;
0278 PropertyChanges { target: audioThumb; opacity: 0.0 } }
0279 ]
0280 transitions: [ Transition {
0281 NumberAnimation { property: "opacity"; duration: audioThumb.isAudioClip ? 0 : 500}
0282 } ]
0283 Rectangle {
0284 color: "black"
0285 opacity: audioThumb.isAudioClip || root.permanentAudiothumb ? 1 : 0.6
0286 anchors.fill: parent
0287 }
0288 Rectangle {
0289 color: "yellow"
0290 opacity: 0.3
0291 height: parent.height
0292 x: controller.zoneIn * timeScale - (audioThumb.width/root.zoomFactor * root.zoomStart)
0293 width: (controller.zoneOut - controller.zoneIn) * timeScale
0294 visible: controller.zoneIn > 0 || controller.zoneOut < duration - 1
0295 }
0296 Repeater {
0297 id: streamThumb
0298 model: controller.audioStreams.length
0299 onCountChanged: {
0300 thumbTimer.start()
0301 }
0302 property double streamHeight: audioThumb.height / streamThumb.count
0303 Item {
0304 anchors.fill: parent
0305 TimelineWaveform {
0306 anchors.right: parent.right
0307 anchors.left: parent.left
0308 height: streamThumb.streamHeight
0309 property int aChannels: controller.audioChannels[model.index]
0310 y: model.index * height
0311 channels: aChannels
0312 binId: controller.clipId
0313 audioStream: controller.audioStreams[model.index]
0314 isFirstChunk: false
0315 format: controller.audioThumbFormat
0316 normalize: controller.audioThumbNormalize
0317 scaleFactor: audioThumb.width / (root.duration - 1) / root.zoomFactor
0318 waveInPoint: (root.duration - 1) * root.zoomStart * aChannels
0319 waveOutPointWithUpdate: (root.duration - 1) * (root.zoomStart + root.zoomFactor) * aChannels
0320 fillColor1: root.thumbColor1
0321 fillColor2: root.thumbColor2
0322 }
0323 Rectangle {
0324 width: parent.width
0325 y: (model.index + 1) * streamThumb.streamHeight
0326 height: 1
0327 visible: streamThumb.count > 1 && model.index < streamThumb.count - 1
0328 color: 'yellow'
0329 }
0330 }
0331 }
0332 Rectangle {
0333 color: "red"
0334 width: 1
0335 height: parent.height
0336 x: controller.position * timeScale - (audioThumb.width/root.zoomFactor * root.zoomStart)
0337 }
0338 MouseArea {
0339 id: thumbMouseArea
0340 anchors.fill: parent
0341 acceptedButtons: Qt.LeftButton
0342 hoverEnabled: true
0343 propagateComposedEvents: true
0344 onPressed: {
0345 if (audioThumb.isAudioClip && mouseY < audioSeekZone.y) {
0346 mouse.accepted = false
0347 return
0348 }
0349 var pos = Math.max(mouseX, 0)
0350 pos += audioThumb.width/root.zoomFactor * root.zoomStart
0351 controller.setPosition(Math.min(pos / root.timeScale, root.duration));
0352 }
0353 onPositionChanged: mouse => {
0354 if (!(mouse.modifiers & Qt.ShiftModifier) && audioThumb.isAudioClip && mouseY < audioSeekZone.y) {
0355 mouse.accepted = false
0356 return
0357 }
0358 if (mouse.modifiers & Qt.ShiftModifier || pressed) {
0359 var pos = Math.max(mouseX, 0)
0360 pos += audioThumb.width/root.zoomFactor * root.zoomStart
0361 controller.setPosition(Math.min(pos / root.timeScale, root.duration));
0362 }
0363 }
0364 onWheel: wheel => {
0365 if (wheel.modifiers & Qt.ControlModifier) {
0366 if (wheel.angleDelta.y < 0) {
0367 // zoom out
0368 clipMonitorRuler.zoomOutRuler(wheel.x)
0369 } else {
0370 // zoom in
0371 clipMonitorRuler.zoomInRuler(wheel.x)
0372 }
0373 } else {
0374 wheel.accepted = false
0375 }
0376
0377 }
0378 Rectangle {
0379 id: audioSeekZone
0380 width: parent.width
0381 height: parent.height / 6
0382 anchors.centerIn: parent
0383 anchors.verticalCenterOffset: audioThumb.isAudioClip ? parent.height * 5 / 12 : 0
0384 visible: audioThumb.isAudioClip && thumbMouseArea.containsMouse && thumbMouseArea.mouseY > y
0385 color: 'yellow'
0386 opacity: 0.5
0387 Rectangle {
0388 width: parent.width
0389 height: 1
0390 color: '#000'
0391 anchors.top: parent.top
0392 }
0393 // frame ticks
0394 Repeater {
0395 id: rulerAudioTicks
0396 model: parent.width / root.frameSize + 2
0397 Rectangle {
0398 x: index * root.frameSize - (clipMonitorRuler.rulerZoomOffset % root.frameSize)
0399 anchors.top: audioSeekZone.top
0400 height: (index % 5) ? audioSeekZone.height / 6 : audioSeekZone.height / 3
0401 width: 1
0402 color: '#000'
0403 opacity: 0.8
0404 }
0405 }
0406 }
0407 }
0408 }
0409 Menu {
0410 id: contextMenu
0411 Instantiator {
0412 model: controller.lastClips
0413 MenuItem {
0414 text: modelData
0415 font: fixedFont
0416 onTriggered: {
0417 controller.selectClip(index)
0418 //showAnimate.restart()
0419 }
0420 }
0421 // Update model when needed
0422 onObjectAdded: (index, object) => contextMenu.insertItem(index, object)
0423 onObjectRemoved: (index, object) => contextMenu.removeItem(object)
0424 }
0425 }
0426 Rectangle {
0427 id: labelContainer
0428 width: childrenRect.width
0429 height: childrenRect.height
0430 anchors {
0431 top: parent.top
0432 horizontalCenter: parent.horizontalCenter
0433 }
0434 color: clipNameLabel.hovered || contextMenu.visible ? "#CC222277" : "#88222277"
0435 border.color: clipNameLabel.hovered ? "#000000" : "transparent"
0436 border.width: 1
0437 radius: 2
0438 visible: clipName != ""
0439 ToolButton {
0440 id: clipNameLabel
0441 hoverEnabled: true
0442 icon.name: controller.lastClips.length > 1 ? "arrow-down" : ""
0443 text: clipName
0444 enabled: labelContainer.opacity > 0.5
0445 onTextChanged: {
0446 if (thumbTimer.running) {
0447 thumbTimer.stop()
0448 }
0449 thumbTimer.start()
0450 }
0451 bottomPadding: 0
0452 topPadding: 0
0453 topInset: 0
0454 bottomInset: 0
0455 SequentialAnimation {
0456 id: showAnimate
0457 running: false
0458 NumberAnimation { target: labelContainer; duration: 3000 }
0459 onStarted: {
0460 contextMenu.opacity = 1
0461 }
0462 onFinished: {
0463 if (contextMenu.visible) {
0464 contextMenu.close()
0465 }
0466 fadeAnimate.start()
0467 }
0468 }
0469 ParallelAnimation {
0470 id: fadeAnimate
0471 running: false
0472 NumberAnimation { target: labelContainer; property: "opacity"; to: 0; duration: 1000 }
0473 }
0474 onClicked: {
0475 if (controller.lastClips.length > 1) {
0476 if (contextMenu.visible) {
0477 contextMenu.close()
0478 } else {
0479 contextMenu.popup()
0480 }
0481 }
0482 }
0483 onHoveredChanged: {
0484 if (hovered) {
0485 showAnimate.stop()
0486 opacity = 1
0487 } else {
0488 if (!contextMenu.visible) {
0489 showAnimate.restart()
0490 }
0491 }
0492 }
0493 }
0494 }
0495
0496 Label {
0497 id: timecode
0498 font.family: fontMetrics.font.family
0499 font.pointSize: 1.5 * fontMetrics.font.pointSize
0500 objectName: "timecode"
0501 color: "#ffffff"
0502 padding: 2
0503 background: Rectangle {
0504 color: "#66000000"
0505 }
0506 text: controller.timecode
0507 visible: root.showTimecode
0508 anchors {
0509 right: parent.right
0510 bottom: parent.bottom
0511 bottomMargin: overlayMargin
0512 }
0513 }
0514 Label {
0515 id: fpsdropped
0516 font.family: fontMetrics.font.family
0517 font.pointSize: 1.5 * fontMetrics.font.pointSize
0518 objectName: "fpsdropped"
0519 color: "#ffffff"
0520 padding: 2
0521 background: Rectangle {
0522 color: root.dropped ? "#99ff0000" : "#66004400"
0523 }
0524 text: i18n("%1fps", root.fps)
0525 visible: root.showFps
0526 anchors {
0527 right: timecode.visible ? timecode.left : parent.right
0528 bottom: parent.bottom
0529 bottomMargin: overlayMargin
0530 }
0531 }
0532 Label {
0533 id: labelSpeed
0534 font: fixedFont
0535 anchors {
0536 left: parent.left
0537 top: parent.top
0538 }
0539 visible: Math.abs(controller.speed) > 1
0540 text: "x" + controller.speed
0541 color: "white"
0542 background: Rectangle {
0543 color: "darkgreen"
0544 }
0545 padding: 5
0546 horizontalAlignment: TextInput.AlignHCenter
0547 }
0548 Label {
0549 id: inPoint
0550 font: fixedFont
0551 anchors {
0552 left: parent.left
0553 bottom: parent.bottom
0554 bottomMargin: overlayMargin
0555 }
0556 visible: root.showMarkers && controller.position == controller.zoneIn
0557 text: controller.zoneIn == controller.zoneOut ? i18n("In/Out Point") : i18n("In Point")
0558 color: "white"
0559 background: Rectangle {
0560 color: "#228b22"
0561 }
0562 padding:4
0563 horizontalAlignment: TextInput.AlignHCenter
0564 MouseArea {
0565 id: inPointArea
0566 anchors.fill: parent
0567 hoverEnabled: true
0568 }
0569 }
0570 Label {
0571 id: outPoint
0572 font: fixedFont
0573 anchors {
0574 left: inPoint.visible ? inPoint.right : parent.left
0575 bottom: parent.bottom
0576 bottomMargin: overlayMargin
0577 }
0578 visible: root.showMarkers && controller.position == controller.zoneOut && controller.zoneOut > controller.zoneIn
0579 text: i18n("Out Point")
0580 color: "white"
0581 background: Rectangle {
0582 color: "#770000"
0583 }
0584 padding: 4
0585 horizontalAlignment: TextInput.AlignHCenter
0586 MouseArea {
0587 id: outPointArea
0588 anchors.fill: parent
0589 hoverEnabled: true
0590 }
0591 }
0592 TextField {
0593 id: marker
0594 font: fixedFont
0595 objectName: "markertext"
0596 activeFocusOnPress: true
0597 text: controller.markerComment
0598 onEditingFinished: {
0599 root.markerText = marker.displayText
0600 marker.focus = false
0601 root.editCurrentMarker()
0602 }
0603 anchors {
0604 left: outPoint.visible ? outPoint.right : inPoint.visible ? inPoint.right : parent.left
0605 bottom: parent.bottom
0606 bottomMargin: overlayMargin
0607 }
0608 visible: root.showMarkers && text != ""
0609 height: inPoint.height
0610 width: fontMetrics.boundingRect(displayText).width + 10
0611 horizontalAlignment: displayText == text ? TextInput.AlignHCenter : TextInput.AlignLeft
0612 background: Rectangle {
0613 color: controller.markerColor
0614 }
0615 color: "#000"
0616 padding: 0
0617 maximumLength: 20
0618 }
0619 }
0620
0621 Rectangle {
0622 // Audio or video only drag zone
0623 id: dragZone
0624 property string uuid
0625 x: 2
0626 y: inPoint.visible || outPoint.visible || marker.visible ? parent.height - inPoint.height - height - 2 - overlayMargin : parent.height - height - 2 - overlayMargin
0627 width: childrenRect.width
0628 height: childrenRect.height
0629 color: Qt.rgba(activePalette.highlight.r, activePalette.highlight.g, activePalette.highlight.b, 0.7)
0630 radius: 4
0631 opacity: (dragAudioArea.containsMouse || dragVideoArea.containsMouse || thumbMouseArea.containsMouse || marker.hovered || inPointArea.containsMouse || outPointArea.containsMouse || dragAudioArea.pressed || dragVideoArea.pressed
0632 || (barOverArea.containsMouse && (barOverArea.mouseY >= (parent.height - inPoint.height - height - 2 - (audioThumb.height + root.zoomOffset) - root.baseUnit)))) ? 1 : 0
0633 visible: controller.clipHasAV
0634 onOpacityChanged: {
0635 if (opacity == 1) {
0636 videoDragButton.x = 0
0637 videoDragButton.y = 0
0638 audioDragButton.x = videoDragButton.x + videoDragButton.width
0639 audioDragButton.y = 0
0640 }
0641 }
0642 Row {
0643 id: dragRow
0644 ToolButton {
0645 id: videoDragButton
0646 icon.name: "kdenlive-show-video"
0647 opacity: dragAudioArea.pressed ? 0 : 1
0648 focusPolicy: Qt.NoFocus
0649 Drag.active: dragVideoArea.drag.active
0650 Drag.dragType: Drag.Automatic
0651 Drag.mimeData: {
0652 "text/producerslist" : "V" + controller.clipId + "/" + controller.zoneIn + "/" + (controller.zoneOut - 1),
0653 "text/dragid" : dragZone.uuid
0654 }
0655 Drag.onDragStarted: {
0656 dragZone.uuid = controller.getUuid()
0657 }
0658 Drag.onDragFinished: dropAction => {
0659 root.endDrag()
0660 root.captureRightClick = false
0661 }
0662 MouseArea {
0663 id: dragVideoArea
0664 hoverEnabled: true
0665 anchors.fill: videoDragButton
0666 cursorShape: Qt.PointingHand
0667 drag.target: videoDragButton
0668 onPressed: mouse => {
0669 root.captureRightClick = true
0670 mouse.accepted = true
0671 }
0672 onReleased: mouse => {
0673 mouse.accepted = true
0674 root.captureRightClick = false
0675 }
0676 }
0677 }
0678 ToolButton {
0679 id: audioDragButton
0680 opacity: dragVideoArea.pressed ? 0 : 1
0681 icon.name: "audio-volume-medium"
0682 focusPolicy: Qt.NoFocus
0683 Drag.active: dragAudioArea.drag.active
0684 Drag.dragType: Drag.Automatic
0685 Drag.mimeData: {
0686 "text/producerslist" : "A" + controller.clipId + "/" + controller.zoneIn + "/" + (controller.zoneOut - 1),
0687 "text/dragid" : dragZone.uuid
0688 }
0689 Drag.onDragStarted: {
0690 dragZone.uuid = controller.getUuid()
0691 }
0692 Drag.onDragFinished: {
0693 root.endDrag()
0694 root.captureRightClick = false
0695 }
0696 MouseArea {
0697 id: dragAudioArea
0698 hoverEnabled: true
0699 anchors.fill: audioDragButton
0700 cursorShape: Qt.PointingHand
0701 drag.target: audioDragButton
0702 onPressed: mouse => {
0703 root.captureRightClick = true
0704 mouse.accepted = true
0705 }
0706 onReleased: mouse => {
0707 mouse.accepted = true
0708 root.captureRightClick = false
0709 }
0710 }
0711 }
0712 }
0713 }
0714 }
0715 Item {
0716 id: clipJobInfo
0717 x: sceneToolBar.visible && sceneToolBar.rightSide == false ? sceneToolBar.width + 10 : 10
0718 y: 10
0719 width: parent.width - 20
0720 height: childrenRect.height
0721 visible: root.showClipJobs && controller.clipId > 0
0722 Column {
0723 Repeater {
0724 model: controller.runningJobs
0725 delegate: Rectangle {
0726 id: jobContainer
0727 property var uuid: controller.jobsUuids[model.index]
0728 width: childrenRect.width + 4
0729 height: jobLabel.height + progressBar.height + 4
0730 color: "#80333333"
0731 radius: 5
0732 MouseArea {
0733 id: jobsArea
0734 hoverEnabled: true
0735 anchors.fill: parent
0736 }
0737 Row {
0738 id: labelRow
0739 MonitorToolButton {
0740 id: iconButton
0741 iconName: "window-close"
0742 anchors.leftMargin: 4
0743 height: jobLabel.height
0744 width: height
0745 toolTipText: i18n("Terminate Job")
0746 onClicked: controller.terminateJob(uuid)
0747 }
0748 Text {
0749 id: jobLabel
0750 horizontalAlignment: Text.AlignLeft
0751 anchors.leftMargin: 4
0752 padding: 2
0753 text: modelData
0754 font.pointSize: fontMetrics.font.pointSize
0755 elide: Text.ElideMiddle
0756 color: 'white'
0757 }
0758 }
0759 Rectangle {
0760 id: progressBar
0761 anchors.top: labelRow.bottom
0762 anchors.left: parent.left
0763 anchors.right: parent.right
0764 anchors.leftMargin: 4
0765 anchors.rightMargin: 4
0766 height: 6
0767 radius: 2
0768 color: "#33ffffff"
0769 border {
0770 color: "#99000000"
0771 width: 1
0772 }
0773 Rectangle {
0774 anchors.fill: parent
0775 anchors.margins: 1
0776 color: 'steelblue'
0777 anchors.rightMargin: (parent.width - 2) * (100 - controller.jobsProgress[model.index]) / 100
0778 }
0779 }
0780 }
0781 }
0782 }
0783 }
0784 MonitorRuler {
0785 id: clipMonitorRuler
0786 anchors {
0787 left: root.left
0788 right: root.right
0789 bottom: root.bottom
0790 }
0791 height: controller.rulerHeight
0792 Repeater {
0793 model:controller.clipBounds
0794 anchors.fill: parent
0795 Rectangle {
0796 anchors.top: parent.top
0797 anchors.topMargin: 1
0798 property point bd: controller.clipBoundary(model.index)
0799 x: bd.x * root.timeScale - (audioThumb.width/root.zoomFactor * root.zoomStart)
0800 width: bd.y * root.timeScale
0801 height: 2
0802 color: 'goldenrod'
0803 }
0804 }
0805 }
0806 }