[vlmc-devel] Timeline: Implement scaling the timeline by key pressing and zoomSlider

Yikai Lu git at videolan.org
Sat Jul 16 17:24:26 CEST 2016


vlmc | branch: master | Yikai Lu <luyikei.qmltu at gmail.com> | Sun Jul 17 00:13:51 2016 +0900| [ed02b238bc7e3ab745d93d12bd55cc16b34c4c44] | committer: Yikai Lu

Timeline: Implement scaling the timeline by key pressing and zoomSlider

> https://code.videolan.org/videolan/vlmc/commit/ed02b238bc7e3ab745d93d12bd55cc16b34c4c44
---

 src/Gui/timeline/Cursor.qml         |   4 +
 src/Gui/timeline/Track.qml          |   2 +-
 src/Gui/timeline/TrackContainer.qml |   2 +-
 src/Gui/timeline/main.qml           | 193 ++++++++++++++++++++++++------------
 4 files changed, 134 insertions(+), 67 deletions(-)

diff --git a/src/Gui/timeline/Cursor.qml b/src/Gui/timeline/Cursor.qml
index e60d9fc..14e2423 100644
--- a/src/Gui/timeline/Cursor.qml
+++ b/src/Gui/timeline/Cursor.qml
@@ -7,5 +7,9 @@ Rectangle {
     onXChanged: {
          x = x > initPosOfCursor ? x : initPosOfCursor;
     }
+
+    function position() {
+        return ptof( x - initPosOfCursor );
+    }
 }
 
diff --git a/src/Gui/timeline/Track.qml b/src/Gui/timeline/Track.qml
index 9f93094..4d566d9 100644
--- a/src/Gui/timeline/Track.qml
+++ b/src/Gui/timeline/Track.qml
@@ -2,7 +2,7 @@ import QtQuick 2.0
 
 Item {
     id: track
-    width: page.width
+    width: parent.width
     height: trackHeight
     z: 10
 
diff --git a/src/Gui/timeline/TrackContainer.qml b/src/Gui/timeline/TrackContainer.qml
index 6bcd649..895e2ce 100644
--- a/src/Gui/timeline/TrackContainer.qml
+++ b/src/Gui/timeline/TrackContainer.qml
@@ -7,7 +7,7 @@ ListView {
     property string type
     property ListModel tracks
 
-    width: page.width
+    width: parent.width
     height: tracks.count * trackHeight
     verticalLayoutDirection: isUpward ? ListView.BottomToTop  : ListView.TopToBottom
 
diff --git a/src/Gui/timeline/main.qml b/src/Gui/timeline/main.qml
index 314bc07..30e720d 100644
--- a/src/Gui/timeline/main.qml
+++ b/src/Gui/timeline/main.qml
@@ -9,11 +9,13 @@ Rectangle {
     border.width: 0
     focus: true
 
+    property int length // in frames
     property int initPosOfCursor: 100
-    property int ppu: 10 // Pixels Per minimum Unit
-    property int unit: 3000 // In milliseconds so ppu / unit = Pixels Per milliseconds
+    property double ppu: 10 // Pixels Per minimum Unit
+    property double unit: 3000 // In milliseconds therefore ppu / unit = Pixels Per milliseconds
     property double fps: 29.97
     property int maxZ: 100
+    property int scale: 10
     property var selectedClips: []
 
     property int trackHeight: 30
@@ -156,6 +158,53 @@ Rectangle {
 
     }
 
+    function zoomIn( ratio ) {
+        var newPpu = ppu;
+        var newUnit = unit;
+        newPpu *= ratio;
+
+        // Don't be too narrow.
+        while ( newPpu < 10 ) {
+            newPpu *= 2;
+            newUnit *= 2;
+        }
+
+        // Don't be too distant.
+        while ( newPpu > 20 ) {
+            newPpu /= 2;
+            newUnit /= 2;
+        }
+
+        // Can't be more precise than 1000msec / fps.
+        var mUnit = 1000 / fps;
+
+        if ( newUnit < mUnit ) {
+            newPpu /= ratio; // Restore the original scale.
+            newPpu *= mUnit / newPpu;
+            newUnit = mUnit;
+        }
+
+        // Make unit a multiple of fps. This can change the scale but let's ignore it.
+        newUnit -= newUnit % mUnit;
+
+        var cursorPos = cursor.position();
+
+        // If "almost" the same value, don't bother redrawing the ruler.
+        if ( Math.abs( unit - newUnit ) > 0.01 )
+            unit = newUnit;
+
+        if ( Math.abs( ppu - newPpu ) > 0.0001 )
+            ppu = newPpu;
+
+        cursor.x = ftop( cursorPos ) + initPosOfCursor;
+
+        // Let's scroll to the cursor position!
+        var newContentX = cursor.x - sView.width / 2;
+        // Never show the background behind the timeline
+        if ( newContentX >= 0 && sView.flickableItem.contentWidth - newContentX > sView.width  )
+            sView.flickableItem.contentX = newContentX;
+    }
+
     function dragFinished() {
         var length = selectedClips.length;
         for ( var i = length - 1; i >= 0; --i ) {
@@ -214,67 +263,70 @@ Rectangle {
         }
     }
 
-    Ruler {
-        id: ruler
-        z: 1000
-    }
-
-    Cursor {
-        id: cursor
-        z: 2000
+    ScrollView {
+        id: sView
         height: page.height
-        x: initPosOfCursor
-    }
-
-    Rectangle {
-        id: borderBottomOfRuler
         width: page.width
-        height: 1
-        color: "#111111"
-        anchors.top: ruler.bottom
-    }
+        flickableItem.contentWidth: Math.max( page.width, ftop( length ) + initPosOfCursor + 100 )
 
-    ScrollView {
-        id: sView
-        anchors.top: borderBottomOfRuler.bottom
-        anchors.bottom: page.bottom
-        anchors.right: page.right
-        anchors.left: page.left
-
-        Column {
-            TrackContainer {
-                id: videoTrackContainer
-                type: "Video"
-                isUpward: true
-                tracks: trackContainers.get( 0 )["tracks"]
-            }
+        Flickable {
 
-            Rectangle {
-                height: 20
-                width: page.width
-                gradient: Gradient {
-                    GradientStop {
-                        position: 0.00;
-                        color: "#797979"
-                    }
+            Column {
+                width: parent.width
 
-                    GradientStop {
-                        position: 0.748
-                        color: "#959697"
-                    }
+                Ruler {
+                    id: ruler
+                    z: 1000
+                }
+
+                Rectangle {
+                    id: borderBottomOfRuler
+                    width: parent.width
+                    height: 1
+                    color: "#111111"
+                }
+
+                TrackContainer {
+                    id: videoTrackContainer
+                    type: "Video"
+                    isUpward: true
+                    tracks: trackContainers.get( 0 )["tracks"]
+                }
 
-                    GradientStop {
-                        position: 0.986
-                        color: "#858f99"
+                Rectangle {
+                    height: 20
+                    width: parent.width
+                    gradient: Gradient {
+                        GradientStop {
+                            position: 0.00;
+                            color: "#797979"
+                        }
+
+                        GradientStop {
+                            position: 0.748
+                            color: "#959697"
+                        }
+
+                        GradientStop {
+                            position: 0.986
+                            color: "#858f99"
+                        }
                     }
                 }
+
+                TrackContainer {
+                    id: audioTrackContainer
+                    type: "Audio"
+                    isUpward: false
+                    tracks: trackContainers.get( 1 )["tracks"]
+                }
             }
 
-            TrackContainer {
-                id: audioTrackContainer
-                type: "Audio"
-                isUpward: false
-                tracks: trackContainers.get( 1 )["tracks"]
+            Cursor {
+                id: cursor
+                z: 2000
+                height: page.height
+                x: initPosOfCursor
             }
         }
     }
@@ -303,24 +355,35 @@ Rectangle {
     Keys.onPressed: {
         if ( event.key === Qt.Key_Delete ) {
             removeClipDialog.visible = true;
-            event.accepted = true;
         }
+        else if ( event.key === Qt.Key_Plus && event.modifiers & Qt.ControlModifier )
+        {
+            zoomIn( 2 );
+        }
+        else if ( event.key === Qt.Key_Minus && event.modifiers & Qt.ControlModifier )
+        {
+            zoomIn( 0.5 );
+        }
+        event.accepted = true;
     }
 
     Connections {
         target: workflow
         onLengthChanged: {
-            if ( ruler.width < ftop( length ) + 100 ) {
-                var newPpu = ppu;
-                var newUnit = unit;
-                newPpu *= width / ( ftop( length ) + 100 )
-                while ( newPpu < 5 ) {
-                    newPpu *= 2;
-                    newUnit *= 2;
-                }
-                unit = newUnit;
-                ppu = newPpu;
-            }
+            page.length = length;
+            zoomIn( sView.width / ( ftop( length ) + initPosOfCursor + 100 ) );
+        }
+    }
+
+    Connections {
+        target: mainwindow
+        onScaleChanged: {
+            // 10 levels
+            if ( scale < scaleLevel * 10 )
+                zoomIn( 0.5 );
+            else if ( scale > scaleLevel * 10 )
+                zoomIn( 2 );
+            scale = scaleLevel * 10;
         }
     }
 }



More information about the Vlmc-devel mailing list