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 }