47
47
from classes .app import get_app
48
48
from classes .logger import log
49
49
from classes .timeline import TimelineSync
50
- from classes .query import File , Clip , Transition , Marker , Track
51
- from classes .metrics import *
52
- from classes .version import *
50
+ from classes .query import Clip , Transition , Marker , Track
51
+ from classes .metrics import (
52
+ track_metric_session , track_metric_screen ,
53
+ track_metric_error , track_exception_stacktrace ,
54
+ )
55
+ from classes .version import get_current_Version
53
56
from classes .conversion import zoomToSeconds , secondsToZoom
54
57
from classes .thumbnail import httpThumbnailServerThread
55
58
from windows .models .files_model import FilesModel
@@ -753,7 +756,7 @@ def promptImageSequence(self, filename=None):
753
756
)
754
757
return bool (ret == QMessageBox .Yes )
755
758
756
- def actionAdd_to_Timeline_trigger (self , event ):
759
+ def actionAdd_to_Timeline_trigger (self , checked = False ):
757
760
# Loop through selected files
758
761
files = self .selected_files ()
759
762
@@ -776,7 +779,7 @@ def actionAdd_to_Timeline_trigger(self, event):
776
779
else :
777
780
log .info ('canceled' )
778
781
779
- def actionExportVideo_trigger (self , event ):
782
+ def actionExportVideo_trigger (self , checked = True ):
780
783
# show window
781
784
from windows .export import Export
782
785
win = Export ()
@@ -787,37 +790,37 @@ def actionExportVideo_trigger(self, event):
787
790
else :
788
791
log .info ('Export Video add cancelled' )
789
792
790
- def actionExportEDL_trigger (self , event ):
793
+ def actionExportEDL_trigger (self , checked = True ):
791
794
"""Export EDL File"""
792
795
export_edl ()
793
796
794
- def actionExportFCPXML_trigger (self , event ):
797
+ def actionExportFCPXML_trigger (self , checked = True ):
795
798
"""Export XML (Final Cut Pro) File"""
796
799
export_xml ()
797
800
798
- def actionImportEDL_trigger (self , event ):
801
+ def actionImportEDL_trigger (self , checked = True ):
799
802
"""Import EDL File"""
800
803
import_edl ()
801
804
802
- def actionImportFCPXML_trigger (self , event ):
805
+ def actionImportFCPXML_trigger (self , checked = True ):
803
806
"""Import XML (Final Cut Pro) File"""
804
807
import_xml ()
805
808
806
- def actionUndo_trigger (self , event ):
809
+ def actionUndo_trigger (self , checked = True ):
807
810
log .info ('actionUndo_trigger' )
808
811
get_app ().updates .undo ()
809
812
810
813
# Update the preview
811
814
self .refreshFrameSignal .emit ()
812
815
813
- def actionRedo_trigger (self , event ):
816
+ def actionRedo_trigger (self , checked = True ):
814
817
log .info ('actionRedo_trigger' )
815
818
get_app ().updates .redo ()
816
819
817
820
# Update the preview
818
821
self .refreshFrameSignal .emit ()
819
822
820
- def actionPreferences_trigger (self , event ):
823
+ def actionPreferences_trigger (self , checked = True ):
821
824
# Stop preview thread
822
825
self .SpeedSignal .emit (0 )
823
826
ui_util .setup_icon (self , self .actionPlay , "actionPlay" , "media-playback-start" )
@@ -843,74 +846,74 @@ def actionPreferences_trigger(self, event):
843
846
# Restore normal cursor
844
847
get_app ().restoreOverrideCursor ()
845
848
846
- def actionFilesShowAll_trigger (self , event ):
849
+ def actionFilesShowAll_trigger (self , checked = True ):
847
850
self .refreshFilesSignal .emit ()
848
851
849
- def actionFilesShowVideo_trigger (self , event ):
852
+ def actionFilesShowVideo_trigger (self , checked = True ):
850
853
self .refreshFilesSignal .emit ()
851
854
852
- def actionFilesShowAudio_trigger (self , event ):
855
+ def actionFilesShowAudio_trigger (self , checked = True ):
853
856
self .refreshFilesSignal .emit ()
854
857
855
- def actionFilesShowImage_trigger (self , event ):
858
+ def actionFilesShowImage_trigger (self , checked = True ):
856
859
self .refreshFilesSignal .emit ()
857
860
858
- def actionTransitionsShowAll_trigger (self , event ):
861
+ def actionTransitionsShowAll_trigger (self , checked = True ):
859
862
self .refreshTransitionsSignal .emit ()
860
863
861
- def actionTransitionsShowCommon_trigger (self , event ):
864
+ def actionTransitionsShowCommon_trigger (self , checked = True ):
862
865
self .refreshTransitionsSignal .emit ()
863
866
864
- def actionHelpContents_trigger (self , event ):
867
+ def actionHelpContents_trigger (self , checked = True ):
865
868
try :
866
869
webbrowser .open ("https://www.openshot.org/%suser-guide/?app-menu" % info .website_language (), new = 1 )
867
870
except Exception :
868
871
QMessageBox .information (self , "Error !" , "Unable to open the online help" )
869
872
log .error ("Unable to open the Help Contents" , exc_info = 1 )
870
873
871
- def actionAbout_trigger (self , event ):
874
+ def actionAbout_trigger (self , checked = True ):
872
875
"""Show about dialog"""
873
876
from windows .about import About
874
877
win = About ()
875
878
# Run the dialog event loop - blocking interaction on this window during this time
876
879
win .exec_ ()
877
880
878
- def actionReportBug_trigger (self , event ):
881
+ def actionReportBug_trigger (self , checked = True ):
879
882
try :
880
883
webbrowser .open ("https://www.openshot.org/%sissues/new/?app-menu" % info .website_language (), new = 1 )
881
884
except Exception :
882
885
QMessageBox .information (self , "Error !" , "Unable to open the Bug Report GitHub Issues web page" )
883
886
log .error ("Unable to open the Bug Report page" , exc_info = 1 )
884
887
885
- def actionAskQuestion_trigger (self , event ):
888
+ def actionAskQuestion_trigger (self , checked = True ):
886
889
try :
887
890
webbrowser .open ("https://www.reddit.com/r/OpenShot/" , new = 1 )
888
891
except Exception :
889
892
QMessageBox .information (self , "Error !" , "Unable to open the official OpenShot subreddit web page" )
890
893
log .error ("Unable to open the subreddit page" , exc_info = 1 )
891
894
892
- def actionTranslate_trigger (self , event ):
895
+ def actionTranslate_trigger (self , checked = True ):
893
896
try :
894
897
webbrowser .open ("https://translations.launchpad.net/openshot/2.0" , new = 1 )
895
898
except Exception :
896
899
QMessageBox .information (self , "Error !" , "Unable to open the Translation web page" )
897
900
log .error ("Unable to open the translation page" , exc_info = 1 )
898
901
899
- def actionDonate_trigger (self , event ):
902
+ def actionDonate_trigger (self , checked = True ):
900
903
try :
901
904
webbrowser .open ("https://www.openshot.org/%sdonate/?app-menu" % info .website_language (), new = 1 )
902
905
except Exception :
903
906
QMessageBox .information (self , "Error !" , "Unable to open the Donate web page" )
904
907
log .error ("Unable to open the donation page" , exc_info = 1 )
905
908
906
- def actionUpdate_trigger (self , event ):
909
+ def actionUpdate_trigger (self , checked = True ):
907
910
try :
908
911
webbrowser .open ("https://www.openshot.org/%sdownload/?app-toolbar" % info .website_language (), new = 1 )
909
912
except Exception :
910
913
QMessageBox .information (self , "Error !" , "Unable to open the Download web page" )
911
914
log .error ("Unable to open the download page" , exc_info = 1 )
912
915
913
- def actionPlay_trigger (self , event , force = None ):
916
+ def actionPlay_trigger (self , checked , force = None ):
914
917
if force == "pause" :
915
918
self .actionPlay .setChecked (False )
916
919
elif force == "play" :
@@ -926,7 +929,7 @@ def actionPlay_trigger(self, event, force=None):
926
929
ui_util .setup_icon (self , self .actionPlay , "actionPlay" ) # to default
927
930
self .PauseSignal .emit ()
928
931
929
- def actionPreview_File_trigger (self , event ):
932
+ def actionPreview_File_trigger (self , checked = True ):
930
933
""" Preview the selected media file """
931
934
log .info ('actionPreview_File_trigger' )
932
935
@@ -964,7 +967,7 @@ def SetPlayheadFollow(self, enable_follow):
964
967
""" Enable / Disable follow mode """
965
968
self .timeline .SetPlayheadFollow (enable_follow )
966
969
967
- def actionFastForward_trigger (self , event ):
970
+ def actionFastForward_trigger (self , checked = True ):
968
971
969
972
# Get the video player object
970
973
player = self .preview_thread .player
@@ -977,7 +980,7 @@ def actionFastForward_trigger(self, event):
977
980
if player .Mode () == openshot .PLAYBACK_PAUSED :
978
981
self .actionPlay .trigger ()
979
982
980
- def actionRewind_trigger (self , event ):
983
+ def actionRewind_trigger (self , checked = True ):
981
984
982
985
# Get the video player object
983
986
player = self .preview_thread .player
@@ -990,20 +993,20 @@ def actionRewind_trigger(self, event):
990
993
if player .Mode () == openshot .PLAYBACK_PAUSED :
991
994
self .actionPlay .trigger ()
992
995
993
- def actionJumpStart_trigger (self , event ):
996
+ def actionJumpStart_trigger (self , checked = True ):
994
997
log .info ("actionJumpStart_trigger" )
995
998
996
999
# Seek to the 1st frame
997
1000
self .SeekSignal .emit (1 )
998
1001
999
- def actionJumpEnd_trigger (self , event ):
1002
+ def actionJumpEnd_trigger (self , checked = True ):
1000
1003
log .info ("actionJumpEnd_trigger" )
1001
1004
1002
1005
# Determine last frame (based on clips) & seek there
1003
1006
max_frame = get_app ().window .timeline_sync .timeline .GetMaxFrame ()
1004
1007
self .SeekSignal .emit (max_frame )
1005
1008
1006
- def actionSaveFrame_trigger (self , event ):
1009
+ def actionSaveFrame_trigger (self , checked = True ):
1007
1010
log .info ("actionSaveFrame_trigger" )
1008
1011
1009
1012
# Translate object
@@ -1158,7 +1161,7 @@ def renumber_all_layers(self, insert_at=None, stride=1000000):
1158
1161
" (inserted {} at {})" .format (insert_num , insert_at ) if insert_at else "" )
1159
1162
)
1160
1163
1161
- def actionAddTrack_trigger (self , event ):
1164
+ def actionAddTrack_trigger (self , checked = True ):
1162
1165
log .info ("actionAddTrack_trigger" )
1163
1166
1164
1167
# Get # of tracks
@@ -1171,7 +1174,7 @@ def actionAddTrack_trigger(self, event):
1171
1174
track .data = {"number" : track_number , "y" : 0 , "label" : "" , "lock" : False }
1172
1175
track .save ()
1173
1176
1174
- def actionAddTrackAbove_trigger (self , event ):
1177
+ def actionAddTrackAbove_trigger (self , checked = True ):
1175
1178
# Get selected track
1176
1179
all_tracks = get_app ().project .get ("layers" )
1177
1180
selected_layer_id = self .selected_tracks [0 ]
@@ -1218,7 +1221,7 @@ def actionAddTrackAbove_trigger(self, event):
1218
1221
# Temporarily for debugging
1219
1222
log .info ("Tracks after: {}" .format ([{x ['number' ]: x ['id' ]} for x in reversed (tracks )]))
1220
1223
1221
- def actionAddTrackBelow_trigger (self , event ):
1224
+ def actionAddTrackBelow_trigger (self , checked = True ):
1222
1225
# Get selected track
1223
1226
all_tracks = get_app ().project .get ("layers" )
1224
1227
selected_layer_id = self .selected_tracks [0 ]
@@ -1268,23 +1271,23 @@ def actionAddTrackBelow_trigger(self, event):
1268
1271
# Temporarily for debugging
1269
1272
log .info ("Tracks after: {}" .format ([{x ['number' ]: x ['id' ]} for x in reversed (tracks )]))
1270
1273
1271
- def actionArrowTool_trigger (self , event ):
1274
+ def actionArrowTool_trigger (self , checked = True ):
1272
1275
log .info ("actionArrowTool_trigger" )
1273
1276
1274
- def actionSnappingTool_trigger (self , event ):
1277
+ def actionSnappingTool_trigger (self , checked = True ):
1275
1278
log .info ("actionSnappingTool_trigger" )
1276
1279
1277
1280
# Enable / Disable snapping mode
1278
1281
self .timeline .SetSnappingMode (self .actionSnappingTool .isChecked ())
1279
1282
1280
- def actionRazorTool_trigger (self , event ):
1283
+ def actionRazorTool_trigger (self , checked = True ):
1281
1284
"""Toggle razor tool on and off"""
1282
1285
log .info ('actionRazorTool_trigger' )
1283
1286
1284
1287
# Enable / Disable razor mode
1285
- self .timeline .SetRazorMode (self . actionRazorTool . isChecked () )
1288
+ self .timeline .SetRazorMode (checked )
1286
1289
1287
- def actionAddMarker_trigger (self , event ):
1290
+ def actionAddMarker_trigger (self , checked = True ):
1288
1291
log .info ("actionAddMarker_trigger" )
1289
1292
1290
1293
# Get player object
@@ -1302,7 +1305,6 @@ def actionAddMarker_trigger(self, event):
1302
1305
marker .data = {"position" : position , "icon" : "blue.png" }
1303
1306
marker .save ()
1304
1307
1305
-
1306
1308
def findAllMarkerPositions (self ):
1307
1309
"""Build and return a list of all seekable locations for the currently-selected timeline elements"""
1308
1310
@@ -1322,31 +1324,36 @@ def getTimelineObjectPositions(obj):
1322
1324
positions .append (clip_stop_time )
1323
1325
1324
1326
# add all keyframes
1325
- for property in obj .data :
1326
- try :
1327
- for point in obj .data [property ]["Points" ] :
1327
+ for property in obj .data :
1328
+ try :
1329
+ for point in obj .data [property ]["Points" ]:
1328
1330
keyframe_time = (point ["co" ]["X" ]- 1 )/ fps_float - obj .data ["start" ] + obj .data ["position" ]
1329
- if keyframe_time > clip_start_time and keyframe_time < clip_stop_time :
1331
+ if clip_start_time < keyframe_time < clip_stop_time :
1330
1332
positions .append (keyframe_time )
1331
1333
except (TypeError , KeyError ):
1332
1334
pass
1333
1335
1334
-
1335
1336
# Add all Effect keyframes
1336
1337
if "effects" in obj .data :
1337
1338
for effect_data in obj .data ["effects" ]:
1338
1339
for property in effect_data :
1339
1340
try :
1340
1341
for point in effect_data [property ]["Points" ]:
1341
1342
keyframe_time = (point ["co" ]["X" ]- 1 )/ fps_float + clip_orig_time
1342
- if keyframe_time > clip_start_time and keyframe_time < clip_stop_time :
1343
+ if clip_start_time < keyframe_time < clip_stop_time :
1343
1344
positions .append (keyframe_time )
1344
1345
except (TypeError , KeyError ):
1345
1346
pass
1346
1347
1347
1348
return positions
1348
1349
1349
- all_marker_positions = []
1350
+ # We can always jump to the beginning of the timeline
1351
+ all_marker_positions = [0 ]
1352
+
1353
+ # If nothing is selected, also add the end of the last clip
1354
+ if not self .selected_clips + self .selected_transitions :
1355
+ all_marker_positions .append (
1356
+ get_app ().window .timeline_sync .timeline .GetMaxTime ())
1350
1357
1351
1358
# Get list of marker and important positions (like selected clip bounds)
1352
1359
for marker in Marker .filter ():
@@ -1371,7 +1378,7 @@ def getTimelineObjectPositions(obj):
1371
1378
1372
1379
return all_marker_positions
1373
1380
1374
- def actionPreviousMarker_trigger (self , event ):
1381
+ def actionPreviousMarker_trigger (self , checked = True ):
1375
1382
log .info ("actionPreviousMarker_trigger" )
1376
1383
1377
1384
# Calculate current position (in seconds)
@@ -1403,7 +1410,7 @@ def actionPreviousMarker_trigger(self, event):
1403
1410
get_app ().window .refreshFrameSignal .emit ()
1404
1411
get_app ().window .propertyTableView .select_frame (frame_to_seek )
1405
1412
1406
- def actionNextMarker_trigger (self , event ):
1413
+ def actionNextMarker_trigger (self , checked = True ):
1407
1414
log .info ("actionNextMarker_trigger" )
1408
1415
1409
1416
# Calculate current position (in seconds)
@@ -1435,7 +1442,7 @@ def actionNextMarker_trigger(self, event):
1435
1442
get_app ().window .refreshFrameSignal .emit ()
1436
1443
get_app ().window .propertyTableView .select_frame (frame_to_seek )
1437
1444
1438
- def actionCenterOnPlayhead_trigger (self , event ):
1445
+ def actionCenterOnPlayhead_trigger (self , checked = True ):
1439
1446
""" Center the timeline on the current playhead position """
1440
1447
self .timeline .centerOnPlayhead ()
1441
1448
0 commit comments