Changeset View
Changeset View
Standalone View
Standalone View
src/timeline2/view/qml/timeline.qml
Context not available. | |||||
124 | scrollTimer.running = false | 124 | scrollTimer.running = false | ||
---|---|---|---|---|---|
125 | } | 125 | } | ||
126 | 126 | | |||
127 | function initDrag(itemObject, itemCoord, itemId, itemPos, itemTrack, isComposition) { | ||||
128 | dragProxy.x = itemCoord.x | ||||
129 | dragProxy.y = itemCoord.y | ||||
130 | dragProxy.width = itemCoord.width | ||||
131 | dragProxy.height = itemCoord.height | ||||
132 | dragProxy.masterObject = itemObject | ||||
133 | dragProxy.draggedItem = itemId | ||||
134 | dragProxy.sourceTrack = itemTrack | ||||
135 | dragProxy.sourceFrame = itemPos | ||||
136 | dragProxy.isComposition = isComposition | ||||
137 | } | ||||
138 | function endDrag() { | ||||
139 | dragProxy.draggedItem = -1 | ||||
140 | dragProxy.x = 0 | ||||
141 | dragProxy.y = 0 | ||||
142 | dragProxy.width = 0 | ||||
143 | dragProxy.height = 0 | ||||
144 | } | ||||
145 | | ||||
127 | property int headerWidth: timeline.headerWidth() | 146 | property int headerWidth: timeline.headerWidth() | ||
128 | property int activeTool: 0 | 147 | property int activeTool: 0 | ||
129 | property real baseUnit: fontMetrics.font.pointSize | 148 | property real baseUnit: fontMetrics.font.pointSize | ||
Context not available. | |||||
507 | width: headerWidth | 526 | width: headerWidth | ||
508 | height: model.trackHeight | 527 | height: model.trackHeight | ||
509 | selected: false | 528 | selected: false | ||
510 | current: item === timeline.activeTrack | 529 | current: itemId === timeline.activeTrack | ||
511 | trackId: item | 530 | trackId: itemId | ||
512 | onIsLockedChanged: tracksRepeater.itemAt(index).isLocked = isLocked | 531 | onIsLockedChanged: tracksRepeater.itemAt(index).isLocked = isLocked | ||
513 | collapsed: height <= collapsedHeight | 532 | collapsed: height <= collapsedHeight | ||
514 | onMyTrackHeightChanged: { | 533 | onMyTrackHeightChanged: { | ||
Context not available. | |||||
622 | rubberSelect.width = 0 | 641 | rubberSelect.width = 0 | ||
623 | rubberSelect.height = 0 | 642 | rubberSelect.height = 0 | ||
624 | } else if (mouse.button & Qt.LeftButton) { | 643 | } else if (mouse.button & Qt.LeftButton) { | ||
644 | if (dragProxy.draggedItem > -1) { | ||||
645 | mouse.accepted = false | ||||
646 | return | ||||
647 | } | ||||
625 | if (root.activeTool === 2 && mouse.y > ruler.height) { | 648 | if (root.activeTool === 2 && mouse.y > ruler.height) { | ||
626 | // spacer tool | 649 | // spacer tool | ||
627 | var y = mouse.y - ruler.height | 650 | var y = mouse.y - ruler.height | ||
Context not available. | |||||
663 | scim = false | 686 | scim = false | ||
664 | } | 687 | } | ||
665 | onPositionChanged: { | 688 | onPositionChanged: { | ||
689 | if (dragProxy.draggedItem > -1) { | ||||
690 | mouse.accepted = false | ||||
691 | return | ||||
692 | } | ||||
666 | root.mousePosChanged(Math.round((mouse.x + scrollView.flickableItem.contentX) / timeline.scaleFactor)) | 693 | root.mousePosChanged(Math.round((mouse.x + scrollView.flickableItem.contentX) / timeline.scaleFactor)) | ||
667 | ruler.showZoneLabels = mouse.y < ruler.height | 694 | ruler.showZoneLabels = mouse.y < ruler.height | ||
668 | if ((mouse.modifiers & Qt.ShiftModifier) && mouse.buttons === Qt.LeftButton && !rubberSelect.visible) { | 695 | if ((mouse.modifiers & Qt.ShiftModifier) && mouse.buttons === Qt.LeftButton && !rubberSelect.visible) { | ||
Context not available. | |||||
694 | // Move group | 721 | // Move group | ||
695 | var track = controller.getClipTrackId(spacerGroup) | 722 | var track = controller.getClipTrackId(spacerGroup) | ||
696 | var frame = Math.round((mouse.x + scrollView.flickableItem.contentX) / timeline.scaleFactor) + spacerFrame - spacerClickFrame | 723 | var frame = Math.round((mouse.x + scrollView.flickableItem.contentX) / timeline.scaleFactor) + spacerFrame - spacerClickFrame | ||
697 | frame = controller.suggestClipMove(spacerGroup, track, frame, root.snapping, false); | 724 | frame = controller.suggestClipMove(spacerGroup, track, frame, root.snapping); | ||
698 | controller.requestClipMove(spacerGroup, track, frame, true, false, false) | | |||
699 | continuousScrolling(mouse.x + scrollView.flickableItem.contentX) | 725 | continuousScrolling(mouse.x + scrollView.flickableItem.contentX) | ||
700 | } | 726 | } | ||
701 | scim = true | 727 | scim = true | ||
Context not available. | |||||
748 | timeline.seekPosition = Math.min(timeline.position + 10, timeline.fullDuration - 1) | 774 | timeline.seekPosition = Math.min(timeline.position + 10, timeline.fullDuration - 1) | ||
749 | } | 775 | } | ||
750 | } | 776 | } | ||
751 | | ||||
752 | Column { | 777 | Column { | ||
753 | Flickable { | 778 | Flickable { | ||
754 | // Non-slider scroll area for the Ruler. | 779 | // Non-slider scroll area for the Ruler. | ||
Context not available. | |||||
795 | height: Math.max(trackHeaders.height, scrollView.height - scrollView.__horizontalScrollBar.height) | 820 | height: Math.max(trackHeaders.height, scrollView.height - scrollView.__horizontalScrollBar.height) | ||
796 | color: activePalette.window | 821 | color: activePalette.window | ||
797 | id: tracksContainerArea | 822 | id: tracksContainerArea | ||
823 | Rectangle { | ||||
824 | // Drag proxy, responsible for clip / composition move | ||||
825 | id: dragProxy | ||||
826 | x: 0 | ||||
827 | y: 0 | ||||
828 | width: 0 | ||||
829 | height: 0 | ||||
830 | property int draggedItem: -1 | ||||
831 | property int sourceTrack | ||||
832 | property int sourceFrame | ||||
833 | property bool isComposition | ||||
834 | property var masterObject | ||||
835 | color: 'green' | ||||
836 | opacity: 0.8 | ||||
837 | MouseArea { | ||||
838 | id: dragProxyArea | ||||
839 | anchors.fill: parent | ||||
840 | drag.target: parent | ||||
841 | drag.axis: Drag.XAxis | ||||
842 | drag.smoothed: false | ||||
843 | property int dragFrame | ||||
844 | property bool shiftClick: false | ||||
845 | cursorShape: pressed ? Qt.ClosedHandCursor : Qt.OpenHandCursor | ||||
846 | onPressed: { | ||||
847 | dragFrame = -1 | ||||
848 | timeline.activeTrack = dragProxy.sourceTrack | ||||
849 | if (mouse.modifiers & Qt.ShiftModifier) { | ||||
850 | if (timeline.selection.indexOf(dragProxy.draggedItem) == -1) { | ||||
851 | timeline.addSelection(dragProxy.draggedItem) | ||||
852 | } else { | ||||
853 | timeline.removeSelection(dragProxy.draggedItem) | ||||
854 | endDrag() | ||||
855 | shiftClick = true | ||||
856 | return | ||||
857 | } | ||||
858 | shiftClick = true | ||||
859 | } else { | ||||
860 | if (timeline.selection.indexOf(dragProxy.draggedItem) == -1) { | ||||
861 | timeline.selection = [ dragProxy.draggedItem ] | ||||
862 | } | ||||
863 | shiftClick = false | ||||
864 | } | ||||
865 | timeline.showAsset(dragProxy.draggedItem) | ||||
866 | root.stopScrolling = true | ||||
867 | clipBeingMovedId = dragProxy.draggedItem | ||||
868 | if (dragProxy.draggedItem > -1) { | ||||
869 | var tk = controller.getItemTrackId(dragProxy.draggedItem) | ||||
870 | var x = controller.getItemPosition(dragProxy.draggedItem) | ||||
871 | var posx = Math.round((parent.x)/ root.timeScale) | ||||
872 | if (tk != Logic.getTrackIdFromPos(parent.y) || x != posx) { | ||||
873 | console.log('INCORRECT DRAG, ABORTING\n!!!!!!!!!!') | ||||
874 | dragProxy.draggedItem = -1 | ||||
875 | mouse.accepted = false | ||||
876 | } else { | ||||
877 | focus = true; | ||||
878 | dragProxy.masterObject.originalX = dragProxy.masterObject.x | ||||
879 | dragProxy.masterObject.originalTrackId = dragProxy.masterObject.trackId | ||||
880 | dragProxy.masterObject.forceActiveFocus(); | ||||
881 | if (!dragProxy.masterObject.selected) { | ||||
882 | dragProxy.masterObject.clicked(dragProxy.masterObject, mouse.modifiers == Qt.ShiftModifier) | ||||
883 | } | ||||
884 | } | ||||
885 | } else { | ||||
886 | mouse.accepted = false | ||||
887 | parent.x = 0 | ||||
888 | parent.y = 0 | ||||
889 | parent.width = 0 | ||||
890 | parent.height = 0 | ||||
891 | } | ||||
892 | } | ||||
893 | onPositionChanged: { | ||||
894 | if (!shiftClick && dragProxy.draggedItem > -1 && mouse.buttons === Qt.LeftButton) { | ||||
895 | continuousScrolling(mouse.x + parent.x) | ||||
896 | var mapped = tracksContainerArea.mapFromItem(dragProxy, mouse.x, mouse.y).x | ||||
897 | root.mousePosChanged(Math.round(mapped / timeline.scaleFactor)) | ||||
898 | var posx = Math.round((parent.x)/ root.timeScale) | ||||
899 | var posy = Math.min(Math.max(0, mouse.y + parent.y), tracksContainerArea.height) | ||||
900 | var tId = Logic.getTrackIdFromPos(posy) | ||||
901 | timeline.activeTrack = tId | ||||
902 | console.log('+ + RQST ITEM MOVE: ', posx, ' TK: ', tId) | ||||
903 | if (dragProxy.isComposition) { | ||||
904 | dragFrame = controller.suggestCompositionMove(dragProxy.draggedItem, tId, posx, root.snapping) | ||||
905 | } else { | ||||
906 | dragFrame = controller.suggestClipMove(dragProxy.draggedItem, tId, posx, root.snapping) | ||||
907 | } | ||||
908 | var delta = dragFrame - dragProxy.sourceFrame | ||||
909 | if (delta != 0) { | ||||
910 | var s = timeline.timecode(Math.abs(delta)) | ||||
911 | // remove leading zeroes | ||||
912 | if (s.substring(0, 3) === '00:') | ||||
913 | s = s.substring(3) | ||||
914 | s = ((delta < 0)? '-' : (delta > 0)? '+' : '') + s | ||||
915 | bubbleHelp.show(parent.x, ruler.height, s) | ||||
916 | } else bubbleHelp.hide() | ||||
917 | } | ||||
918 | } | ||||
919 | onReleased: { | ||||
920 | clipBeingMovedId = -1 | ||||
921 | if (!shiftClick && dragProxy.draggedItem > -1 && dragFrame > -1) { | ||||
922 | var tId = controller.getItemTrackId(dragProxy.draggedItem) | ||||
923 | if (dragProxy.isComposition) { | ||||
924 | controller.requestCompositionMove(dragProxy.draggedItem, dragProxy.sourceTrack, dragProxy.sourceFrame, dragProxy.sourceTrack != tId, false, false) | ||||
925 | controller.requestCompositionMove(dragProxy.draggedItem, tId, dragFrame , true, true, true) | ||||
926 | } else { | ||||
927 | controller.requestClipMove(dragProxy.draggedItem, dragProxy.sourceTrack, dragProxy.sourceFrame, dragProxy.sourceTrack != tId, false, false) | ||||
928 | controller.requestClipMove(dragProxy.draggedItem, tId, dragFrame , true, true, true) | ||||
929 | } | ||||
930 | bubbleHelp.hide() | ||||
931 | } | ||||
932 | } | ||||
933 | } | ||||
934 | } | ||||
798 | MouseArea { | 935 | MouseArea { | ||
799 | anchors.fill: parent | 936 | anchors.fill: parent | ||
800 | acceptedButtons: Qt.NoButton | 937 | acceptedButtons: Qt.NoButton | ||
801 | onWheel: zoomByWheel(wheel) | 938 | onWheel: zoomByWheel(wheel) | ||
802 | cursorShape: tracksArea.cursorShape | 939 | cursorShape: dragProxyArea.drag.active ? Qt.ClosedHandCursor : tracksArea.cursorShape | ||
803 | } | 940 | } | ||
804 | Column { | 941 | Column { | ||
805 | // These make the striped background for the tracks. | 942 | // These make the striped background for the tracks. | ||
Context not available. | |||||
931 | id: trackDelegateModel | 1068 | id: trackDelegateModel | ||
932 | model: multitrack | 1069 | model: multitrack | ||
933 | delegate: Track { | 1070 | delegate: Track { | ||
934 | model: multitrack | 1071 | trackModel: multitrack | ||
935 | rootIndex: trackDelegateModel.modelIndex(index) | 1072 | trackRootIndex: trackDelegateModel.modelIndex(index) | ||
936 | height: trackHeight | 1073 | height: trackHeight | ||
937 | timeScale: timeline.scaleFactor | 1074 | timeScale: timeline.scaleFactor | ||
938 | width: tracksContainerArea.width | 1075 | width: tracksContainerArea.width | ||
939 | isAudio: audio | 1076 | isAudio: audio | ||
940 | trackThumbsFormat: thumbsFormat | 1077 | trackThumbsFormat: thumbsFormat | ||
941 | isCurrentTrack: item === timeline.activeTrack | 1078 | isCurrentTrack: itemId === timeline.activeTrack | ||
942 | trackId: item | 1079 | trackId: itemId | ||
943 | onClipClicked: { | | |||
944 | timeline.activeTrack = track.trackId | | |||
945 | if (shiftClick === 1) { | | |||
946 | timeline.addSelection(clip.clipId) | | |||
947 | } else { | | |||
948 | timeline.selection = [ clip.clipId ] | | |||
949 | } | | |||
950 | timeline.showAsset(clip.clipId) | | |||
951 | } | | |||
952 | onClipDragged: { | | |||
953 | continuousScrolling(x) | | |||
954 | // Show distance moved as time in a "bubble" help. | | |||
955 | var delta = Math.round((clip.x / timeline.scaleFactor) - Math.round(clip.originalX) / timeline.scaleFactor) | | |||
956 | if (delta != 0) { | | |||
957 | var s = timeline.timecode(Math.abs(delta)) | | |||
958 | // remove leading zeroes | | |||
959 | if (s.substring(0, 3) === '00:') | | |||
960 | s = s.substring(3) | | |||
961 | s = ((delta < 0)? '-' : (delta > 0)? '+' : '') + s | | |||
962 | bubbleHelp.show(x, mapToItem(null, x, clip.y).y, s) | | |||
963 | clipBeingMovedId = clip.clipId | | |||
964 | } else bubbleHelp.hide() | | |||
965 | } | | |||
966 | onClipDropped: { | | |||
967 | console.log(" + + + ++ + DROPPED + + + + + + +"); | | |||
968 | scrollTimer.running = false | | |||
969 | bubbleHelp.hide() | | |||
970 | clipBeingMovedId = -1 | | |||
971 | } | | |||
972 | onCompositionDropped: { | | |||
973 | console.log(" + + + ++ + COMPOSITION DROPPED + + + + + + +"); | | |||
974 | scrollTimer.running = false | | |||
975 | bubbleHelp.hide() | | |||
976 | clipBeingMovedId = -1 | | |||
977 | } | | |||
978 | onClipDraggedToTrack: { | | |||
979 | var y = Math.max(0, pos - ruler.height) | | |||
980 | var activeTrack = Logic.getTrackIndexFromPos(y) | | |||
981 | var frame = Math.max(0, Math.round(clip.x / timeScale)) | | |||
982 | if (activeTrack >= 0 && activeTrack < tracksRepeater.count) { | | |||
983 | var track = tracksRepeater.itemAt(activeTrack) | | |||
984 | //console.log('Dragging clip ',clip.clipId,' to track: ', activeTrack, ' - ', y) | | |||
985 | if (controller.requestClipMove(clip.clipId, track.trackId, frame, false, false, false)) { | | |||
986 | // Query the model to make sure on which track the clip is | | |||
987 | timeline.activeTrack = controller.getClipTrackId(clip.clipId) | | |||
988 | track = Logic.getTrackById(timeline.activeTrack) | | |||
989 | clip.height = track.height | | |||
990 | clip.y = track.y - Logic.getTrackById(clip.originalTrackId).y | | |||
991 | clip.trackId = track.trackId | | |||
992 | clip.currentFrame = frame | | |||
993 | } else { | | |||
994 | if (track.trackId != clip.trackId) { | | |||
995 | // check if we can move on existing track | | |||
996 | if (!controller.requestClipMove(clip.clipId, clip.trackId, frame, false, false, false)) { | | |||
997 | // Abort move | | |||
998 | clip.x = clip.currentFrame * timeScale | | |||
999 | } else { | | |||
1000 | clip.x = frame * timeScale | | |||
1001 | clip.currentFrame = frame | | |||
1002 | var delta = Math.round((clip.x - clip.originalX) / timeline.scaleFactor) | | |||
1003 | var s = timeline.timecode(Math.abs(delta)) | | |||
1004 | // remove leading zeroes | | |||
1005 | if (s.substring(0, 3) === '00:') | | |||
1006 | s = s.substring(3) | | |||
1007 | s = ((delta < 0)? '-' : (delta > 0)? '+' : '') + s | | |||
1008 | bubbleHelp.show(xpos, mapToItem(null, x, clip.y).y, s) | | |||
1009 | } | | |||
1010 | } else { | | |||
1011 | // Abort move | | |||
1012 | clip.x = clip.draggedX | | |||
1013 | } | | |||
1014 | } | | |||
1015 | } else { | | |||
1016 | console.log('+ + + + +\nWARNING CLIP DRAGGED TO INVALID TRACK: ',activeTrack,'\n+ + + +'); | | |||
1017 | } | | |||
1018 | } | | |||
1019 | onCompositionDraggedToTrack: { | | |||
1020 | var y = pos - ruler.height | | |||
1021 | var tk = Logic.getTrackIndexFromPos(y) | | |||
1022 | var frame = Math.round(composition.x / timeScale) | | |||
1023 | if (tk >= 0 && tk < tracksRepeater.count) { | | |||
1024 | var track = tracksRepeater.itemAt(tk) | | |||
1025 | timeline.activeTrack = track.trackId | | |||
1026 | if (controller.requestCompositionMove(composition.clipId, track.trackId, frame, false, false)) { | | |||
1027 | composition.reparent(track) | | |||
1028 | composition.trackIndex = track.DelegateModel.itemsIndex | | |||
1029 | composition.trackId = track.trackId | | |||
1030 | } | | |||
1031 | } | | |||
1032 | } | | |||
1033 | Rectangle { | 1080 | Rectangle { | ||
1034 | anchors.right: parent.right | 1081 | anchors.right: parent.right | ||
1035 | anchors.left: parent.left | 1082 | anchors.left: parent.left | ||
Context not available. | |||||
1124 | target: timeline | 1171 | target: timeline | ||
1125 | onPositionChanged: if (!stopScrolling) Logic.scrollIfNeeded() | 1172 | onPositionChanged: if (!stopScrolling) Logic.scrollIfNeeded() | ||
1126 | onFrameFormatChanged: ruler.adjustFormat() | 1173 | onFrameFormatChanged: ruler.adjustFormat() | ||
1127 | /*onDragging: Logic.dragging(pos, duration) | | |||
1128 | onDropped: Logic.dropped() | | |||
1129 | onDropAccepted: Logic.acceptDrop(xml)*/ | | |||
1130 | onSelectionChanged: { | 1174 | onSelectionChanged: { | ||
1131 | //cornerstone.selected = timeline.isMultitrackSelected() | 1175 | //cornerstone.selected = timeline.isMultitrackSelected() | ||
1132 | var selectedTrack = timeline.selectedTrack() | 1176 | var selectedTrack = timeline.selectedTrack() | ||
Context not available. |