Track.qml 12.4 KB
Newer Older
luyikei's avatar
luyikei committed
1 2 3 4
import QtQuick 2.0

Item {
    id: track
5
    width: parent.width
luyikei's avatar
luyikei committed
6 7 8 9 10 11 12
    height: trackHeight
    z: 10

    property int trackId
    property string type
    property ListModel clips

13 14 15 16 17 18
    Rectangle {
        id: clipArea
        x: trackInfo.width
        color: "#222222"
        height: parent.height
        width: track.width - initPosOfCursor
luyikei's avatar
luyikei committed
19

luyikei's avatar
luyikei committed
20
        Rectangle {
21 22 23 24 25 26 27 28 29
            color: "#666666"
            height: 1
            width: parent.width
            anchors.bottom: clipArea.bottom

            Component.onCompleted: {
                if ( track.type === "Video" && track.trackId == 0 )
                {
                    color = "#111111";
luyikei's avatar
luyikei committed
30 31
                }
            }
32
        }
luyikei's avatar
luyikei committed
33

34 35 36 37
        DropArea {
            id: dropArea
            anchors.fill: parent
            keys: ["Clip", "vlmc/uuid"]
luyikei's avatar
luyikei committed
38

39 40 41 42 43 44 45 46 47 48
            // Enum for drop mode
            readonly property var dropMode: {
                "New": 0,
                "Move": 1,
            }

            property string currentUuid
            property var aClipInfo: null
            property var vClipInfo: null

49 50
            property int lastPos: 0
            property int deltaPos: 0
51 52 53 54 55

            onDropped: {
                if ( drop.keys.indexOf( "vlmc/uuid" ) >= 0 ) {
                    aClipInfo = findClipFromTrack( "Audio", trackId, "audioUuid" );
                    vClipInfo = findClipFromTrack( "Video", trackId, "videoUuid" );
56
                    var pos = 0;
57
                    if ( aClipInfo ) {
58
                        pos = aClipInfo["position"];
59
                        removeClipFromTrack( "Audio", trackId, "audioUuid" );
60 61 62
                    }
                    if ( vClipInfo ) {
                        pos = vClipInfo["position"];
63
                        removeClipFromTrack( "Video", trackId, "videoUuid" );
luyikei's avatar
luyikei committed
64
                    }
65
                    workflow.addClip( drop.getDataAsString("vlmc/uuid"), trackId, pos, false );
66 67 68 69 70 71
                    currentUuid = "";
                    aClipInfo = null;
                    vClipInfo = null;
                    clearSelectedClips();
                    adjustTracks( "Audio" );
                    adjustTracks( "Video" );
luyikei's avatar
luyikei committed
72
                }
73
            }
luyikei's avatar
luyikei committed
74

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
            onExited: {
                if ( currentUuid !== "" ) {
                    removeClipFromTrack( "Audio", trackId, "audioUuid" );
                    removeClipFromTrack( "Video", trackId, "videoUuid" );
                }
            }

            onEntered: {
                if ( drag.keys.indexOf( "vlmc/uuid" ) >= 0 ) {
                    clearSelectedClips();
                    if ( currentUuid === drag.getDataAsString( "vlmc/uuid" ) ) {
                        if ( aClipInfo )
                        {
                            aClipInfo["position"] = ptof( drag.x );
                            aClipInfo = addClip( "Audio", trackId, aClipInfo );
luyikei's avatar
luyikei committed
90
                        }
91 92 93 94
                        if ( vClipInfo )
                        {
                            vClipInfo["position"] = ptof( drag.x );
                            vClipInfo = addClip( "Video", trackId, vClipInfo );
luyikei's avatar
luyikei committed
95 96
                        }
                    }
97
                    else {
98
                        var newClipInfo = workflow.libraryClipInfo( drag.getDataAsString( "vlmc/uuid" ) );
99
                        currentUuid = "" + newClipInfo["uuid"];
100 101 102 103 104 105 106 107 108 109
                        newClipInfo["position"] = ptof( drag.x );
                        if ( newClipInfo["audio"] ) {
                            newClipInfo["uuid"] = "audioUuid";
                            aClipInfo = addClip( "Audio", trackId, newClipInfo );
                        }
                        if ( newClipInfo["video"] ) {
                            newClipInfo["uuid"] = "videoUuid";
                            vClipInfo = addClip( "Video", trackId, newClipInfo );
                        }
                    }
110
                    lastPos = ptof( drag.x );
luyikei's avatar
luyikei committed
111
                }
112
                else {
113
                    lastPos = ptof( drag.source.x );
114 115 116
                    // HACK: Call onPositoinChanged forcely here.
                    // x will be rounded so it won't affect actual its position.
                    drag.source.x = drag.source.x + 0.000001;
117
                    drag.source.forcePosition(); // Restore the binding
118
                }
119
            }
luyikei's avatar
luyikei committed
120

121 122 123 124 125 126 127 128 129 130
            onPositionChanged: {
                // If resizing, ignore
                if ( drag.source.resizing === true )
                    return;

                if ( drag.keys.indexOf( "vlmc/uuid" ) >= 0 )
                    var dMode = dropMode.New;
                else
                    dMode = dropMode.Move;

131 132 133 134
                // Scroll to the drag source
                if ( dMode === dropMode.Move )
                    drag.source.scrollToThis();

135
                if ( dMode === dropMode.Move ) {
136 137
                    deltaPos = ptof( drag.source.x ) - lastPos;

138 139 140
                    // Move to the top
                    drag.source.parent.parent.z = ++maxZ;

141
                    // Prepare newTrackId for all the selected clips
142 143 144
                    var oldTrackId = drag.source.newTrackId;
                    drag.source.newTrackId = trackId;

145 146 147
                    sortSelectedClips( trackId - oldTrackId ,deltaPos );
                    var toMove = selectedClips.concat();

148
                    // Check if there is any impossible move
149
                    for ( var i = 0; i < toMove.length; ++i ) {
150
                        var target = findClipItem( toMove[i] );
151
                        if ( target !== drag.source ) {
152 153 154 155
                            var newTrackId = trackId - oldTrackId + target.trackId;
                            if ( newTrackId < 0 )
                            {
                                drag.source.newTrackId = oldTrackId;
156
                                drag.source.forcePosition();
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172

                                // Direction depends on its type
                                drag.source.y +=
                                        drag.source.type === "Video"
                                        ? -( trackHeight * ( oldTrackId - trackId ) )
                                        : trackHeight * ( oldTrackId - trackId )
                                return;
                            }
                        }
                    }

                    for ( i = 0; i < toMove.length; ++i ) {
                        target = findClipItem( toMove[i] );
                        if ( target !== drag.source ) {
                             newTrackId = trackId - oldTrackId + target.trackId;
                            target.newTrackId = Math.max( 0, newTrackId );
173 174
                            if ( target.newTrackId !== target.trackId ) {
                                // Let's move to the new tracks
175 176 177
                                target.clipInfo["selected"] = true;
                                addClip( target.type, target.newTrackId, target.clipInfo );
                                removeClipFromTrack( target.type, target.trackId, target.uuid );
178
                            }
179
                        }
180 181
                    }
                }
182 183
                else {
                    toMove = selectedClips.concat();
184
                    deltaPos = ptof( drag.x ) - lastPos;
185
                }
186

187 188
                while ( toMove.length > 0 ) {
                    target = findClipItem( toMove[0] );
189 190 191
                    var oldPos = target.position;
                    var newPos = findNewPosition( Math.max( oldPos + deltaPos, 0 ), target, drag.source, isMagneticMode );
                    deltaPos = newPos - oldPos;
luyikei's avatar
luyikei committed
192

193
                    // Let's find newX of the linked clip
194
                    for ( i = 0; i < target.linkedClips.length; ++i )
195
                    {
196
                        var linkedClipItem = findClipItem( target.linkedClips[i] );
197

198
                        if ( linkedClipItem ) {
199
                            var newLinkedClipPos = findNewPosition( newPos, linkedClipItem, drag.source, isMagneticMode );
200

201
                            // If linked clip collides
202
                            if ( newLinkedClipPos !== newPos ) {
203 204
                                // Recalculate target's newX
                                // This time, don't use magnets
205 206
                                if ( isMagneticMode === true )
                                {
207 208
                                    newLinkedClipPos = findNewPosition( newPos, linkedClipItem, drag.source, false );
                                    newPos = findNewPosition( newPos, target, drag.source, false );
luyikei's avatar
luyikei committed
209

210
                                    // And if newX collides again, we don't move
211 212
                                    if ( newLinkedClipPos !== newPos )
                                        deltaPos = 0
213
                                    else
214
                                        linkedClipItem.position = target.position; // Link if possible
215 216
                                }
                                else
217
                                    deltaPos = 0;
luyikei's avatar
luyikei committed
218
                            }
219
                            else
220
                                linkedClipItem.position = target.position; // Link if possible
luyikei's avatar
luyikei committed
221

222 223 224
                            var ind = toMove.indexOf( linkedClipItem.uuid );
                            if ( ind > 0 )
                                toMove.splice( ind, 1 );
225
                        }
226
                    }
227

228
                    newPos = oldPos + deltaPos;
229 230 231 232
                    toMove.splice( 0, 1 );
                }
                // END of while ( toMove.length > 0 )

233 234
                if ( deltaPos === 0 && dMode === dropMode.Move ) {
                    drag.source.forcePosition(); // Use the original position
235 236 237 238 239
                    return;
                }

                for ( i = 0; i < selectedClips.length; ++i ) {
                    target = findClipItem( selectedClips[i] );
240
                    newPos = target.position + deltaPos;
241

242
                    // We only want to update the length when the right edge of the timeline
243
                    // is exposed.
244
                    if ( sView.flickableItem.contentX + page.width > sView.width &&
245 246
                            length < newPos + target.length ) {
                        length = newPos + target.length;
247
                    }
248

249
                    target.position = newPos;
250

251 252
                    // Scroll if needed
                    if ( drag.source === target || dMode === dropMode.New )
253
                        target.scrollToThis();
luyikei's avatar
luyikei committed
254
                }
255 256

                if ( dMode === dropMode.Move )
257
                    lastPos = drag.source.position;
258
                else
259
                    lastPos = ptof( drag.x );
luyikei's avatar
luyikei committed
260
            }
261
        }
luyikei's avatar
luyikei committed
262

263 264 265 266 267 268 269 270 271
        Repeater {
            id: repeater
            model: clips
            delegate: Clip {
                height: track.height - 3
                name: model.name
                trackId: model.trackId
                type: track.type
                uuid: model.uuid
272
                libraryUuid: model.libraryUuid
273 274 275
                position: model.position
                begin: model.begin
                end: model.end
276
                length: model.length
277
                clipInfo: model
luyikei's avatar
luyikei committed
278 279 280
            }
        }
    }
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309

    Rectangle {
        id: trackInfo
        x: sView.flickableItem.contentX
        width: initPosOfCursor
        height: parent.height
        color: "#444444"

        Rectangle {
            width: parent.width
            height: 1
            anchors.bottom: parent.bottom
            color: "#111111"
        }

        Rectangle {
            width: 1
            height: parent.height
            anchors.left: parent.left
            color: "#111111"
        }

        Rectangle {
            width: 1
            height: parent.height
            anchors.right: parent.right
            color: "#111111"
        }

310 311
        Text {
            id: trackText
312
            anchors.verticalCenter: parent.verticalCenter
313 314 315
            x: 10
            text: type + " " + ( trackId + 1 )
            color: "white"
316
            font.pointSize: 10
317
        }
318

319 320
        Row {
            anchors.verticalCenter: parent.verticalCenter
321
            x: trackText.y + trackText.contentWidth + 10
322
            spacing: 4
323 324 325 326 327 328 329 330

            PropertyButton {
                id: fxButton
                text: "Fx"
                selected: true

                onSelectedChanged: {
                    if ( selected === false ) {
331
                        workflow.showEffectStack( trackId );
332 333 334 335
                        selected = true;
                    }
                }
            }
336 337
        }
    }
luyikei's avatar
luyikei committed
338 339
}