39
39
import openshot # Python module for libopenshot (required video editing module installed separately)
40
40
from PyQt5 .QtCore import (
41
41
Qt , pyqtSignal , pyqtSlot , QCoreApplication , PYQT_VERSION_STR ,
42
- QTimer , QDateTime , QFileInfo , QUrl ,
42
+ QTimer , QDateTime , QFileInfo , QUrl , QEvent
43
43
)
44
44
from PyQt5 .QtGui import QIcon , QCursor , QKeySequence , QTextCursor
45
45
from PyQt5 .QtWidgets import (
46
46
QMainWindow , QWidget , QDockWidget ,
47
47
QMessageBox , QDialog , QFileDialog , QInputDialog ,
48
48
QAction , QActionGroup , QSizePolicy ,
49
49
QStatusBar , QToolBar , QToolButton ,
50
- QLineEdit , QComboBox , QTextEdit
50
+ QLineEdit , QComboBox , QTextEdit , QShortcut
51
51
)
52
52
53
53
from classes import exceptions , info , qt_types , sentry , ui_util , updates
@@ -98,6 +98,9 @@ class MainWindow(updates.UpdateWatcher, QMainWindow):
98
98
StopSignal = pyqtSignal ()
99
99
SeekSignal = pyqtSignal (int )
100
100
SpeedSignal = pyqtSignal (float )
101
+ SeekPreviousFrame = pyqtSignal ()
102
+ SeekNextFrame = pyqtSignal ()
103
+ PlayPauseToggleSignal = pyqtSignal ()
101
104
RecoverBackup = pyqtSignal ()
102
105
FoundVersionSignal = pyqtSignal (str )
103
106
TransformSignal = pyqtSignal (str )
@@ -1554,6 +1557,43 @@ def actionCenterOnPlayhead_trigger(self, checked=True):
1554
1557
""" Center the timeline on the current playhead position """
1555
1558
self .timeline .centerOnPlayhead ()
1556
1559
1560
+ def handleSeekPreviousFrame (self ):
1561
+ """Handle previous-frame keypress"""
1562
+ player = get_app ().window .preview_thread .player
1563
+ frame_num = player .Position () - 1
1564
+
1565
+ # Seek to previous frame
1566
+ get_app ().window .PauseSignal .emit ()
1567
+ get_app ().window .SpeedSignal .emit (0 )
1568
+ get_app ().window .previewFrameSignal .emit (frame_num )
1569
+
1570
+ # Notify properties dialog
1571
+ get_app ().window .propertyTableView .select_frame (frame_num )
1572
+
1573
+ def handleSeekNextFrame (self ):
1574
+ """Handle next-frame keypress"""
1575
+ player = get_app ().window .preview_thread .player
1576
+ frame_num = player .Position () + 1
1577
+
1578
+ # Seek to next frame
1579
+ get_app ().window .PauseSignal .emit ()
1580
+ get_app ().window .SpeedSignal .emit (0 )
1581
+ get_app ().window .previewFrameSignal .emit (frame_num )
1582
+
1583
+ # Notify properties dialog
1584
+ get_app ().window .propertyTableView .select_frame (frame_num )
1585
+
1586
+ def handlePlayPauseToggleSignal (self ):
1587
+ """Handle play-pause-toggle keypress"""
1588
+ player = get_app ().window .preview_thread .player
1589
+ frame_num = player .Position ()
1590
+
1591
+ # Toggle Play/Pause
1592
+ get_app ().window .actionPlay .trigger ()
1593
+
1594
+ # Notify properties dialog
1595
+ get_app ().window .propertyTableView .select_frame (frame_num )
1596
+
1557
1597
def getShortcutByName (self , setting_name ):
1558
1598
""" Get a key sequence back from the setting name """
1559
1599
s = get_app ().get_settings ()
@@ -3090,12 +3130,44 @@ def initModels(self):
3090
3130
self .emojiListView = EmojisListView (self .emojis_model )
3091
3131
self .tabEmojis .layout ().addWidget (self .emojiListView )
3092
3132
3133
+ def seekPreviousFrame (self ):
3134
+ """Handle previous-frame keypress"""
3135
+ # Ignore certain focused widgets
3136
+ get_app ().window .SeekPreviousFrame .emit ()
3137
+
3138
+ def seekNextFrame (self ):
3139
+ """Handle next-frame keypress"""
3140
+ get_app ().window .SeekNextFrame .emit ()
3141
+
3142
+ def playToggle (self ):
3143
+ """Handle play-pause-toggle keypress"""
3144
+ get_app ().window .PlayPauseToggleSignal .emit ()
3145
+
3146
+ def eventFilter (self , obj , event ):
3147
+ """Filter out certain QShortcuts - for example, arrow keys used
3148
+ in our files, transitions, effects, and emojis views."""
3149
+ if event .type () == QEvent .ShortcutOverride :
3150
+ if self .emojiListView .hasFocus () or self .filesView .hasFocus () or \
3151
+ self .transitionsView .hasFocus () or self .effectsView .hasFocus ():
3152
+ # Mark event as 'handled' so it stops propagating
3153
+ event .accept ()
3154
+
3155
+ elif self .propertyTableView .hasFocus () and \
3156
+ (event .key () == get_app ().window .getShortcutByName ("playToggle" ) or
3157
+ event .key () == get_app ().window .getShortcutByName ("playToggle1" ) or
3158
+ event .key () == get_app ().window .getShortcutByName ("playToggle2" ) or
3159
+ event .key () == get_app ().window .getShortcutByName ("playToggle3" )):
3160
+ # Mark event as 'handled' so it stops propagating
3161
+ event .accept ()
3162
+ return super (MainWindow , self ).eventFilter (obj , event )
3163
+
3093
3164
def __init__ (self , * args ):
3094
3165
3095
3166
# Create main window base class
3096
3167
super ().__init__ (* args )
3097
3168
self .initialized = False
3098
3169
self .shutting_down = False
3170
+ self .installEventFilter (self )
3099
3171
3100
3172
# set window on app for reference during initialization of children
3101
3173
app = get_app ()
@@ -3177,6 +3249,9 @@ def __init__(self, *args):
3177
3249
3178
3250
# Connect signals
3179
3251
self .RecoverBackup .connect (self .recover_backup )
3252
+ self .SeekPreviousFrame .connect (self .handleSeekPreviousFrame )
3253
+ self .SeekNextFrame .connect (self .handleSeekNextFrame )
3254
+ self .PlayPauseToggleSignal .connect (self .handlePlayPauseToggleSignal )
3180
3255
3181
3256
# Create the timeline sync object (used for previewing timeline)
3182
3257
self .timeline_sync = TimelineSync (self )
@@ -3367,3 +3442,13 @@ def __init__(self, *args):
3367
3442
3368
3443
# Main window is initialized
3369
3444
self .initialized = True
3445
+
3446
+ # Use shortcuts to override keypress capturing for arrow keys
3447
+ # These keys are a bit special, and other approaches fail on certain
3448
+ # combinations of OS and Webview backend
3449
+ QShortcut (app .window .getShortcutByName ("seekPreviousFrame" ), self , activated = self .seekPreviousFrame , context = Qt .WindowShortcut )
3450
+ QShortcut (app .window .getShortcutByName ("seekNextFrame" ), self , activated = self .seekNextFrame , context = Qt .WindowShortcut )
3451
+ QShortcut (app .window .getShortcutByName ("playToggle" ), self , activated = self .playToggle , context = Qt .WindowShortcut )
3452
+ QShortcut (app .window .getShortcutByName ("playToggle1" ), self , activated = self .playToggle , context = Qt .WindowShortcut )
3453
+ QShortcut (app .window .getShortcutByName ("playToggle2" ), self , activated = self .playToggle , context = Qt .WindowShortcut )
3454
+ QShortcut (app .window .getShortcutByName ("playToggle3" ), self , activated = self .playToggle , context = Qt .WindowShortcut )
0 commit comments