Warning, /multimedia/kdenlive/src/timeline2/view/qml/Ruler.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2013 Meltytech LLC
0003     SPDX-FileCopyrightText: 2013 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 import com.enums 1.0
0011 
0012 Item {
0013     id: rulerRoot
0014     // The standard width for labels. Depends on format used (frame number or full timecode)
0015     property int labelSize: fontMetrics.boundingRect(timeline.timecode(36000)).width
0016     // The spacing between labels. Depends on labelSize
0017     property real labelSpacing: labelSize
0018     // The space we want between each ticks in the ruler
0019     property real tickSpacing: timeline.scaleFactor
0020     property alias rulerZone : zone
0021     property int workingPreview : timeline.workingPreview
0022     property int labelMod: 1
0023     property bool useTimelineRuler : timeline.useRuler
0024     property int zoneHeight: Math.ceil(root.baseUnit / 2) + 1
0025     property bool showZoneLabels: false
0026     property bool resizeActive: false // Used to decide which mouse cursor we should display
0027     property bool hoverGuide: false
0028     property int cursorShape: resizeActive ? Qt.SizeHorCursor : hoverGuide ? Qt.PointingHandCursor : Qt.ArrowCursor
0029     property var effectZones: timeline.masterEffectZones
0030     property int guideLabelHeight: timeline.showMarkers ? fontMetrics.height : 0
0031     property int previewHeight: Math.ceil(timecodeContainer.height / 5)
0032     property color dimmedColor: (activePalette.text.r + activePalette.text.g + activePalette.text.b > 1.5) ? Qt.darker(activePalette.text, 1.3) : Qt.lighter(activePalette.text, 1.3)
0033     property color dimmedColor2: (activePalette.text.r + activePalette.text.g + activePalette.text.b > 1.5) ? Qt.darker(activePalette.text, 2.2) : Qt.lighter(activePalette.text, 2.2)
0034     
0035     function adjustStepSize() {
0036         if (timeline.scaleFactor > 19) {
0037             // Frame size >= 20 pixels
0038             rulerRoot.tickSpacing = timeline.scaleFactor
0039             // labelSpacing cannot be smaller than 1 frame
0040             rulerRoot.labelSpacing = timeline.scaleFactor > rulerRoot.labelSize * 1.3 ? timeline.scaleFactor : Math.floor(rulerRoot.labelSize/timeline.scaleFactor) * timeline.scaleFactor
0041         } else {
0042             rulerRoot.tickSpacing = Math.floor(3 * root.baseUnit / timeline.scaleFactor) * timeline.scaleFactor
0043             rulerRoot.labelSpacing = (Math.floor(rulerRoot.labelSize/rulerRoot.tickSpacing) + 1) * rulerRoot.tickSpacing
0044         }
0045         rulerRoot.labelMod = Math.max(1, Math.ceil((rulerRoot.labelSize + root.baseUnit) / rulerRoot.tickSpacing))
0046         //console.log('LABELMOD: ', Math.ceil((rulerRoot.labelSize + root.fontUnit) / rulerRoot.tickSpacing)))
0047         tickRepeater.model = Math.ceil(rulercontainer.width / rulerRoot.tickSpacing) + 2
0048     }
0049 
0050     function adjustFormat() {
0051         rulerRoot.labelSize = fontMetrics.boundingRect(timeline.timecode(36000)).width
0052         adjustStepSize()
0053         repaintRuler()
0054     }
0055 
0056     function repaintRuler() {
0057         // Enforce repaint
0058         tickRepeater.model = 0
0059         tickRepeater.model = Math.ceil(rulercontainer.width / rulerRoot.tickSpacing) + 2
0060     }
0061 
0062     // Timeline preview stuff
0063     Repeater {
0064         model: timeline.dirtyChunks
0065         anchors.fill: parent
0066         delegate: Rectangle {
0067             x: modelData * timeline.scaleFactor
0068             anchors.bottom: parent.bottom
0069             anchors.bottomMargin: zoneHeight
0070             width: 25 * timeline.scaleFactor
0071             height: previewHeight
0072             color: 'darkred'
0073         }
0074     }
0075 
0076     Repeater {
0077         model: timeline.renderedChunks
0078         anchors.fill: parent
0079         delegate: Rectangle {
0080             x: modelData * timeline.scaleFactor
0081             anchors.bottom: parent.bottom
0082             anchors.bottomMargin: zoneHeight
0083             width: 25 * timeline.scaleFactor
0084             height: previewHeight
0085             color: 'darkgreen'
0086         }
0087     }
0088     Rectangle {
0089         id: working
0090         x: rulerRoot.workingPreview * timeline.scaleFactor
0091         anchors.bottom: parent.bottom
0092         anchors.bottomMargin: zoneHeight
0093         width: 25 * timeline.scaleFactor
0094         height: previewHeight
0095         color: 'orange'
0096         visible: rulerRoot.workingPreview > -1
0097     }
0098 
0099     // Guides
0100     Repeater {
0101         id: guidesRepeater
0102         model: guidesModel
0103         property int radiusSize: timeline.guidesLocked ? 0 : guideLabelHeight / 2
0104         delegate:
0105         Item {
0106             id: guideRoot
0107             property bool activated : proxy.position == model.frame
0108             z: activated ? 20 : 10
0109             Rectangle {
0110                 id: markerBase
0111                 width: 1
0112                 height: rulerRoot.height
0113                 x: Math.round(model.frame * timeline.scaleFactor)
0114                 color: guideRoot.activated ? Qt.lighter(model.color, 1.3) : model.color
0115                 property int markerId: model.id
0116                 Rectangle {
0117                     
0118                     visible: timeline.showMarkers
0119                     width: mlabel.contentWidth + 4 - guidesRepeater.radiusSize
0120                     height: guideLabelHeight
0121                     color: markerBase.color
0122                     anchors {
0123                         top: parent.top
0124                         left: parent.left
0125                     }
0126                     ToolTip.visible: guideArea.containsMouse
0127                     ToolTip.text: model.comment
0128                     ToolTip.delay: 1000
0129                     ToolTip.timeout: 5000
0130                     Rectangle {
0131                         visible: !timeline.guidesLocked
0132                         color: markerBase.color
0133                         anchors.fill: parent
0134                         radius: guidesRepeater.radiusSize
0135                         anchors.rightMargin: -guidesRepeater.radiusSize - 2
0136                     }
0137                     Rectangle {
0138                         // Shadow delimiting marker start
0139                         width: 1
0140                         height: guideLabelHeight
0141                         color: activePalette.dark
0142                         anchors {
0143                             right: parent.left
0144                         }
0145                     }
0146                     Rectangle {
0147                         // Shadow on marker top
0148                         height: 1
0149                         width: parent.width + guidesRepeater.radiusSize / 2
0150                         color: Qt.darker(markerBase.color, 1.8)
0151                     }
0152                     Text {
0153                         id: mlabel
0154                         text: model.comment
0155                         topPadding: -1
0156                         leftPadding: 2
0157                         rightPadding: 2
0158                         font: miniFont
0159                         color: '#000'
0160                     }
0161                     MouseArea {
0162                         z: 10
0163                         id: guideArea
0164                         anchors.left: parent.left
0165                         anchors.top: parent.top
0166                         width: parent.width + guidesRepeater.radiusSize
0167                         height: parent.height
0168                         acceptedButtons: Qt.LeftButton | Qt.RightButton
0169                         cursorShape: Qt.PointingHandCursor
0170                         hoverEnabled: true
0171                         property int prevFrame
0172                         property int destFrame
0173                         property int movingMarkerId
0174                         property int xOffset: 0
0175                         drag.axis: Drag.XAxis
0176                         onPressed: {
0177                             prevFrame = model.frame
0178                             destFrame = prevFrame
0179                             xOffset = mouseX
0180                             anchors.left = undefined
0181                             movingMarkerId = markerBase.markerId
0182                         }
0183                         onReleased: {
0184                             if (prevFrame != destFrame) {
0185                                 timeline.moveGuideWithoutUndo(movingMarkerId, prevFrame)
0186                                 timeline.moveGuideById(movingMarkerId, destFrame)
0187                             }
0188                             movingMarkerId = -1
0189                             anchors.left = parent.left
0190                         }
0191                         onPositionChanged: mouse => {
0192                             if (pressed) {
0193                                 var newFrame = Math.max(0, Math.round(model.frame + (mouseX - xOffset) / timeline.scaleFactor))
0194                                 newFrame = controller.suggestSnapPoint(newFrame, mouse.modifiers & Qt.ShiftModifier ? -1 : root.snapping)
0195                                 if (newFrame != destFrame) {
0196                                     var frame = timeline.moveGuideWithoutUndo(movingMarkerId, newFrame)
0197                                     if (frame > -1) {
0198                                         destFrame = frame
0199                                     }
0200                                 }
0201                             }
0202                         }
0203                         drag.smoothed: false
0204                         onDoubleClicked: timeline.editGuide(model.frame)
0205                         onClicked: mouse => {
0206                             if (root.activeTool !== ProjectTool.SlipTool) {
0207                                 proxy.position = model.frame
0208                             }
0209                             if (mouse.button == Qt.RightButton) {
0210                                 root.showRulerMenu()
0211                             }
0212                         }
0213                         onEntered: {
0214                             rulerRoot.hoverGuide = true
0215                         }
0216                         onExited: {
0217                             rulerRoot.hoverGuide = false
0218                         }
0219                     }
0220                 }
0221             }
0222         }
0223     }
0224     
0225     // Ruler marks
0226     Item {
0227         id: timecodeContainer
0228         anchors.top: parent.top
0229         anchors.topMargin: guideLabelHeight
0230         anchors.bottom: parent.bottom
0231         anchors.bottomMargin: zoneHeight
0232         anchors.left: parent.left
0233         anchors.right: parent.right
0234     Repeater {
0235         id: tickRepeater
0236         model: Math.ceil(rulercontainer.width / rulerRoot.tickSpacing) + 2
0237         property int offset: Math.floor(scrollView.contentX /rulerRoot.tickSpacing)
0238         Item {
0239             property int realPos: (tickRepeater.offset + index) * rulerRoot.tickSpacing / timeline.scaleFactor
0240             x: Math.round(realPos * timeline.scaleFactor)
0241             height: parent.height
0242             property bool showText: (tickRepeater.offset + index)%rulerRoot.labelMod == 0
0243             Rectangle {
0244                 anchors.bottom: parent.bottom
0245                 height: parent.showText ? root.baseUnit * 0.8 : 4
0246                 width: 1
0247                 color: dimmedColor2
0248             }
0249             Label {
0250                 visible: parent.showText
0251                 anchors.top: parent.top
0252                 text: timeline.timecode(parent.realPos)
0253                 font: miniFont
0254                 color: dimmedColor
0255             }
0256         }
0257     }
0258     }
0259     
0260     RulerZone {
0261         id: zone
0262         Binding {
0263             target: zone
0264             property: "frameIn"
0265             value: timeline.zoneIn
0266         }
0267         Binding {
0268             target: zone
0269             property: "frameOut"
0270             value: timeline.zoneOut
0271         }
0272         color: useTimelineRuler ? Qt.rgba(activePalette.highlight.r,activePalette.highlight.g,activePalette.highlight.b,0.9) :
0273         Qt.rgba(activePalette.highlight.r,activePalette.highlight.g,activePalette.highlight.b,0.5)
0274         anchors.bottom: parent.bottom
0275         height: zoneHeight
0276         function updateZone(start, end, update)
0277         {
0278             timeline.updateZone(start, end, update)
0279         }
0280     }
0281 
0282     // Master effect zones
0283     Repeater {
0284         model: effectZones
0285         Rectangle {
0286             x: effectZones[index].x * timeline.scaleFactor
0287             height: zoneHeight - 1
0288             width: (effectZones[index].y - effectZones[index].x) * timeline.scaleFactor
0289             color: "blueviolet"
0290             anchors.bottom: parent.bottom
0291             opacity: 0.4
0292         }
0293     }
0294 
0295     // Effect zone
0296     RulerZone {
0297         id: effectZone
0298         Binding {
0299             target: effectZone
0300             property: "frameIn"
0301             value: timeline.effectZone.x
0302         }
0303         Binding {
0304             target: effectZone
0305             property: "frameOut"
0306             value: timeline.effectZone.y
0307         }
0308         color: "orchid"
0309         anchors.bottom: parent.bottom
0310         height: zoneHeight - 1
0311         opacity: 0.7
0312         function updateZone(start, end, update)
0313         {
0314             timeline.updateEffectZone(start, end, update)
0315         }
0316     }
0317 }
0318