hydrus/include/ClientGUIShortcuts.py

920 lines
28 KiB
Python
Raw Normal View History

2019-01-09 22:59:03 +00:00
from . import ClientConstants as CC
from . import ClientData
from . import ClientGUICommon
2019-06-26 21:27:18 +00:00
from . import ClientGUIFunctions
2019-09-11 21:51:09 +00:00
from . import ClientGUIScrolledPanels
from . import ClientGUITopLevelWindows
2019-01-09 22:59:03 +00:00
from . import HydrusConstants as HC
from . import HydrusData
from . import HydrusGlobals as HG
from . import HydrusSerialisable
2019-11-14 03:56:30 +00:00
from qtpy import QtCore as QC
from qtpy import QtWidgets as QW
from qtpy import QtGui as QG
from . import QtPorting as QP
2017-05-31 21:50:53 +00:00
2018-05-16 20:09:50 +00:00
def ConvertKeyEventToShortcut( event ):
2019-11-14 03:56:30 +00:00
key = event.key()
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
if key in CC.special_key_shortcut_enum_lookup or ClientData.OrdIsSensibleASCII( key ):
if key in CC.special_key_shortcut_enum_lookup:
shortcut_type = CC.SHORTCUT_TYPE_KEYBOARD_SPECIAL
key = CC.special_key_shortcut_enum_lookup[ key ]
else:
shortcut_type = CC.SHORTCUT_TYPE_KEYBOARD_ASCII
key = int( key )
2018-05-16 20:09:50 +00:00
modifiers = []
2019-11-14 03:56:30 +00:00
if event.modifiers() & QC.Qt.AltModifier:
2018-05-16 20:09:50 +00:00
modifiers.append( CC.SHORTCUT_MODIFIER_ALT )
2019-11-14 03:56:30 +00:00
if HC.PLATFORM_OSX:
ctrl = QC.Qt.MetaModifier
else:
ctrl = QC.Qt.ControlModifier
if event.modifiers() & ctrl:
2018-05-16 20:09:50 +00:00
modifiers.append( CC.SHORTCUT_MODIFIER_CTRL )
2019-11-14 03:56:30 +00:00
if event.modifiers() & QC.Qt.ShiftModifier:
2018-05-16 20:09:50 +00:00
modifiers.append( CC.SHORTCUT_MODIFIER_SHIFT )
2019-11-14 03:56:30 +00:00
if event.modifiers() & QC.Qt.GroupSwitchModifier:
modifiers.append( CC.SHORTCUT_MODIFIER_GROUP_SWITCH )
if event.modifiers() & QC.Qt.KeypadModifier:
modifiers.append( CC.SHORTCUT_MODIFIER_KEYPAD )
shortcut = Shortcut( shortcut_type, key, modifiers )
2018-05-16 20:09:50 +00:00
if HG.gui_report_mode:
HydrusData.ShowText( 'key event caught: ' + repr( shortcut ) )
return shortcut
return None
def ConvertKeyEventToSimpleTuple( event ):
2019-11-14 03:56:30 +00:00
modifier = QC.Qt.NoModifier
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
if event.modifiers() & QC.Qt.AltModifier: modifier = QC.Qt.AltModifier
elif event.modifiers() & QC.Qt.ControlModifier: modifier = QC.Qt.ControlModifier
elif event.modifiers() & QC.Qt.ShiftModifier: modifier = QC.Qt.ShiftModifier
elif event.modifiers() & QC.Qt.KeypadModifier: modifier = QC.Qt.KeypadModifier
elif event.modifiers() & QC.Qt.GroupSwitchModifier: modifier = QC.Qt.GroupSwitchModifier
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
key = event.key()
2018-05-16 20:09:50 +00:00
return ( modifier, key )
def ConvertMouseEventToShortcut( event ):
key = None
2019-11-14 03:56:30 +00:00
if (event.type() == QC.QEvent.MouseButtonPress and event.buttons() & QC.Qt.LeftButton) or (event.type() == QC.QEvent.MouseButtonDblClick and event.button() == QC.Qt.LeftButton):
2018-05-16 20:09:50 +00:00
key = CC.SHORTCUT_MOUSE_LEFT
2019-11-14 03:56:30 +00:00
elif (event.type() == QC.QEvent.MouseButtonPress and event.buttons() & QC.Qt.MiddleButton) or (event.type() == QC.QEvent.MouseButtonDblClick and event.button() == QC.Qt.MiddleButton):
2018-05-16 20:09:50 +00:00
key = CC.SHORTCUT_MOUSE_MIDDLE
2019-11-14 03:56:30 +00:00
elif (event.type() == QC.QEvent.MouseButtonPress and event.buttons() & QC.Qt.RightButton) or (event.type() == QC.QEvent.MouseButtonDblClick and event.button() == QC.Qt.RightButton):
2018-05-16 20:09:50 +00:00
key = CC.SHORTCUT_MOUSE_RIGHT
2019-11-14 03:56:30 +00:00
elif event.type() == QC.QEvent.Wheel and event.angleDelta().y() > 0:
2018-05-16 20:09:50 +00:00
key = CC.SHORTCUT_MOUSE_SCROLL_UP
2019-11-14 03:56:30 +00:00
elif event.type() == QC.QEvent.Wheel and event.angleDelta().y() < 0:
2018-05-16 20:09:50 +00:00
key = CC.SHORTCUT_MOUSE_SCROLL_DOWN
if key is not None:
modifiers = []
2019-11-14 03:56:30 +00:00
if event.modifiers() & QC.Qt.AltModifier:
2018-05-16 20:09:50 +00:00
modifiers.append( CC.SHORTCUT_MODIFIER_ALT )
2019-11-14 03:56:30 +00:00
if event.modifiers() & QC.Qt.ControlModifier:
2018-05-16 20:09:50 +00:00
modifiers.append( CC.SHORTCUT_MODIFIER_CTRL )
2019-11-14 03:56:30 +00:00
if event.modifiers() & QC.Qt.ShiftModifier:
2018-05-16 20:09:50 +00:00
modifiers.append( CC.SHORTCUT_MODIFIER_SHIFT )
2019-11-14 03:56:30 +00:00
if event.modifiers() & QC.Qt.GroupSwitchModifier:
modifiers.append( CC.SHORTCUT_MODIFIER_GROUP_SWITCH )
if event.modifiers() & QC.Qt.KeypadModifier:
modifiers.append( CC.SHORTCUT_MODIFIER_KEYPAD )
2018-05-16 20:09:50 +00:00
shortcut = Shortcut( CC.SHORTCUT_TYPE_MOUSE, key, modifiers )
if HG.gui_report_mode:
HydrusData.ShowText( 'mouse event caught: ' + repr( shortcut ) )
return shortcut
return None
2019-07-03 22:49:27 +00:00
def IShouldCatchShortcutEvent( evt_handler, event = None, child_tlp_classes_who_can_pass_up = None ):
2017-04-19 20:58:30 +00:00
2019-07-03 22:49:27 +00:00
do_focus_test = True
2019-11-14 03:56:30 +00:00
if event is not None and isinstance( event, QG.QWheelEvent ):
2019-07-03 22:49:27 +00:00
2019-11-14 03:56:30 +00:00
do_focus_test = False
2019-06-26 21:27:18 +00:00
2019-07-03 22:49:27 +00:00
if do_focus_test:
if not ClientGUIFunctions.WindowOrSameTLPChildHasFocus( evt_handler ):
2019-06-26 21:27:18 +00:00
2019-07-03 22:49:27 +00:00
if child_tlp_classes_who_can_pass_up is not None:
2019-11-14 03:56:30 +00:00
child_tlp_has_focus = ClientGUIFunctions.WindowOrAnyTLPChildHasFocus( evt_handler ) and isinstance( QW.QApplication.activeWindow(), child_tlp_classes_who_can_pass_up )
2019-07-03 22:49:27 +00:00
if not child_tlp_has_focus:
return False
else:
2019-06-26 21:27:18 +00:00
return False
2017-04-19 20:58:30 +00:00
return True
2018-05-16 20:09:50 +00:00
class Shortcut( HydrusSerialisable.SerialisableBase ):
SERIALISABLE_TYPE = HydrusSerialisable.SERIALISABLE_TYPE_SHORTCUT
SERIALISABLE_NAME = 'Shortcut'
2019-11-14 03:56:30 +00:00
SERIALISABLE_VERSION = 2
2018-05-16 20:09:50 +00:00
def __init__( self, shortcut_type = None, shortcut_key = None, modifiers = None ):
if shortcut_type is None:
2019-11-14 03:56:30 +00:00
shortcut_type = CC.SHORTCUT_TYPE_KEYBOARD_SPECIAL
2018-05-16 20:09:50 +00:00
if shortcut_key is None:
2019-11-14 03:56:30 +00:00
shortcut_key = CC.SHORTCUT_KEY_SPECIAL_F7
2018-05-16 20:09:50 +00:00
if modifiers is None:
modifiers = []
2019-11-14 03:56:30 +00:00
if shortcut_type == CC.SHORTCUT_TYPE_KEYBOARD_ASCII and ClientData.OrdIsAlphaUpper( shortcut_key ):
shortcut_key += 32 # convert A to a
2018-05-16 20:09:50 +00:00
modifiers.sort()
HydrusSerialisable.SerialisableBase.__init__( self )
self._shortcut_type = shortcut_type
self._shortcut_key = shortcut_key
self._modifiers = modifiers
def __eq__( self, other ):
return self.__hash__() == other.__hash__()
def __hash__( self ):
return ( self._shortcut_type, self._shortcut_key, tuple( self._modifiers ) ).__hash__()
def __repr__( self ):
return 'Shortcut: ' + self.ToString()
def _GetSerialisableInfo( self ):
return ( self._shortcut_type, self._shortcut_key, self._modifiers )
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
( self._shortcut_type, self._shortcut_key, self._modifiers ) = serialisable_info
2019-11-14 03:56:30 +00:00
def _UpdateSerialisableInfo( self, version, old_serialisable_info ):
if version == 1:
# these are dicts that convert fixed wx enums to new stuff
wx_to_qt_flat_conversion = {
32 : CC.SHORTCUT_KEY_SPECIAL_SPACE,
8 : CC.SHORTCUT_KEY_SPECIAL_BACKSPACE,
9 : CC.SHORTCUT_KEY_SPECIAL_TAB,
13 : CC.SHORTCUT_KEY_SPECIAL_RETURN,
310 : CC.SHORTCUT_KEY_SPECIAL_PAUSE,
27 : CC.SHORTCUT_KEY_SPECIAL_ESCAPE,
322 : CC.SHORTCUT_KEY_SPECIAL_INSERT,
127 : CC.SHORTCUT_KEY_SPECIAL_DELETE,
315 : CC.SHORTCUT_KEY_SPECIAL_UP,
317 : CC.SHORTCUT_KEY_SPECIAL_DOWN,
314 : CC.SHORTCUT_KEY_SPECIAL_LEFT,
316 : CC.SHORTCUT_KEY_SPECIAL_RIGHT,
313 : CC.SHORTCUT_KEY_SPECIAL_HOME,
312 : CC.SHORTCUT_KEY_SPECIAL_END,
367 : CC.SHORTCUT_KEY_SPECIAL_PAGE_DOWN,
366 : CC.SHORTCUT_KEY_SPECIAL_PAGE_UP,
340 : CC.SHORTCUT_KEY_SPECIAL_F1,
341 : CC.SHORTCUT_KEY_SPECIAL_F2,
342 : CC.SHORTCUT_KEY_SPECIAL_F3,
343 : CC.SHORTCUT_KEY_SPECIAL_F4,
344 : CC.SHORTCUT_KEY_SPECIAL_F5,
345 : CC.SHORTCUT_KEY_SPECIAL_F6,
346 : CC.SHORTCUT_KEY_SPECIAL_F7,
347 : CC.SHORTCUT_KEY_SPECIAL_F8,
348 : CC.SHORTCUT_KEY_SPECIAL_F9,
349 : CC.SHORTCUT_KEY_SPECIAL_F10,
350 : CC.SHORTCUT_KEY_SPECIAL_F11,
351 : CC.SHORTCUT_KEY_SPECIAL_F12
}
# regular keys, but numpad, that are tracked in wx by combined unique enum
wx_to_qt_numpad_ascii_conversion = {
324 : ord( '0' ),
325 : ord( '1' ),
326 : ord( '2' ),
327 : ord( '3' ),
328 : ord( '4' ),
329 : ord( '5' ),
330 : ord( '6' ),
331 : ord( '7' ),
332 : ord( '8' ),
332 : ord( '9' ),
388 : ord( '+' ),
392 : ord( '/' ),
390 : ord( '-' ),
387 : ord( '*' ),
391 : ord( '.' )
}
wx_to_qt_numpad_conversion = {
377 : CC.SHORTCUT_KEY_SPECIAL_UP,
379 : CC.SHORTCUT_KEY_SPECIAL_DOWN,
376 : CC.SHORTCUT_KEY_SPECIAL_LEFT,
378 : CC.SHORTCUT_KEY_SPECIAL_RIGHT,
375 : CC.SHORTCUT_KEY_SPECIAL_HOME,
382 : CC.SHORTCUT_KEY_SPECIAL_END,
381 : CC.SHORTCUT_KEY_SPECIAL_PAGE_DOWN,
380 : CC.SHORTCUT_KEY_SPECIAL_PAGE_UP,
385 : CC.SHORTCUT_KEY_SPECIAL_DELETE,
370 : CC.SHORTCUT_KEY_SPECIAL_ENTER
}
( shortcut_type, shortcut_key, modifiers ) = old_serialisable_info
if shortcut_type == CC.SHORTCUT_TYPE_KEYBOARD_ASCII:
if shortcut_key in wx_to_qt_flat_conversion:
shortcut_type = CC.SHORTCUT_TYPE_KEYBOARD_SPECIAL
shortcut_key = wx_to_qt_flat_conversion[ shortcut_key ]
elif shortcut_key in wx_to_qt_numpad_ascii_conversion:
shortcut_key = wx_to_qt_numpad_ascii_conversion[ shortcut_key ]
modifiers = list( modifiers )
modifiers.append( CC.SHORTCUT_MODIFIER_KEYPAD )
modifiers.sort()
elif shortcut_key in wx_to_qt_numpad_conversion:
shortcut_type = CC.SHORTCUT_TYPE_KEYBOARD_SPECIAL
shortcut_key = wx_to_qt_numpad_conversion[ shortcut_key ]
modifiers = list( modifiers )
modifiers.append( CC.SHORTCUT_MODIFIER_KEYPAD )
modifiers.sort()
if shortcut_type == CC.SHORTCUT_TYPE_KEYBOARD_ASCII:
if ClientData.OrdIsAlphaUpper( shortcut_key ):
shortcut_key += 32 # convert 'A' to 'a'
new_serialisable_info = ( shortcut_type, shortcut_key, modifiers )
return ( 2, new_serialisable_info )
2018-05-16 20:09:50 +00:00
def GetShortcutType( self ):
return self._shortcut_type
def ToString( self ):
components = []
if CC.SHORTCUT_MODIFIER_CTRL in self._modifiers:
components.append( 'ctrl' )
if CC.SHORTCUT_MODIFIER_ALT in self._modifiers:
components.append( 'alt' )
if CC.SHORTCUT_MODIFIER_SHIFT in self._modifiers:
components.append( 'shift' )
2019-11-14 03:56:30 +00:00
if CC.SHORTCUT_MODIFIER_GROUP_SWITCH in self._modifiers:
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
components.append( 'Mode_switch' )
if self._shortcut_type == CC.SHORTCUT_TYPE_MOUSE and self._shortcut_key in CC.shortcut_mouse_string_lookup:
components.append( CC.shortcut_mouse_string_lookup[ self._shortcut_key ] )
elif self._shortcut_type == CC.SHORTCUT_TYPE_KEYBOARD_SPECIAL and self._shortcut_key in CC.special_key_shortcut_str_lookup:
components.append( CC.special_key_shortcut_str_lookup[ self._shortcut_key ] )
elif self._shortcut_type == CC.SHORTCUT_TYPE_KEYBOARD_ASCII and ClientData.OrdIsSensibleASCII( self._shortcut_key ):
if ClientData.OrdIsAlphaUpper( self._shortcut_key ):
2018-05-16 20:09:50 +00:00
components.append( chr( self._shortcut_key + 32 ) ) # + 32 for converting ascii A -> a
else:
2019-11-14 03:56:30 +00:00
components.append( chr( self._shortcut_key ) )
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
else:
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
components.append( 'unknown key' )
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
s = '+'.join( components )
if CC.SHORTCUT_MODIFIER_KEYPAD in self._modifiers:
s += ' (on numpad)'
return s
2018-05-16 20:09:50 +00:00
HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIALISABLE_TYPE_SHORTCUT ] = Shortcut
2019-11-14 03:56:30 +00:00
class ShortcutPanel( QW.QWidget ):
2018-05-16 20:09:50 +00:00
def __init__( self, parent ):
2019-11-14 03:56:30 +00:00
QW.QWidget.__init__( self, parent )
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
self._mouse_radio = QW.QRadioButton( 'mouse', self )
2018-05-16 20:09:50 +00:00
self._mouse_shortcut = ShortcutMouse( self, self._mouse_radio )
2019-11-14 03:56:30 +00:00
self._keyboard_radio = QW.QRadioButton( 'keyboard', self )
2018-05-16 20:09:50 +00:00
self._keyboard_shortcut = ShortcutKeyboard( self, self._keyboard_radio )
#
2019-11-14 03:56:30 +00:00
vbox = QP.VBoxLayout()
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( vbox, ClientGUICommon.BetterStaticText(self,'Mouse events only work for the duplicate and archive/delete filters atm!'), CC.FLAGS_EXPAND_PERPENDICULAR )
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
gridbox = QP.GridLayout( cols = 2 )
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
gridbox.setColumnStretch( 1, 1 )
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( gridbox, self._mouse_radio, CC.FLAGS_VCENTER )
QP.AddToLayout( gridbox, self._mouse_shortcut, CC.FLAGS_EXPAND_BOTH_WAYS )
QP.AddToLayout( gridbox, self._keyboard_radio, CC.FLAGS_VCENTER )
QP.AddToLayout( gridbox, self._keyboard_shortcut, CC.FLAGS_EXPAND_BOTH_WAYS )
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( vbox, gridbox, CC.FLAGS_EXPAND_BOTH_WAYS )
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
self.setLayout( vbox )
2018-05-16 20:09:50 +00:00
def GetValue( self ):
2019-11-14 03:56:30 +00:00
if self._mouse_radio.isChecked():
2018-05-16 20:09:50 +00:00
return self._mouse_shortcut.GetValue()
else:
return self._keyboard_shortcut.GetValue()
def SetValue( self, shortcut ):
if shortcut.GetShortcutType() == CC.SHORTCUT_TYPE_MOUSE:
2019-11-14 03:56:30 +00:00
self._mouse_radio.setChecked( True )
2018-05-16 20:09:50 +00:00
self._mouse_shortcut.SetValue( shortcut )
else:
2019-11-14 03:56:30 +00:00
self._keyboard_radio.setChecked( True )
2018-05-16 20:09:50 +00:00
self._keyboard_shortcut.SetValue( shortcut )
2019-11-14 03:56:30 +00:00
class ShortcutKeyboard( QW.QLineEdit ):
2018-05-16 20:09:50 +00:00
def __init__( self, parent, related_radio = None ):
2019-11-14 03:56:30 +00:00
self._shortcut = Shortcut()
2018-05-16 20:09:50 +00:00
self._related_radio = related_radio
2019-11-14 03:56:30 +00:00
QW.QLineEdit.__init__( self, parent )
2018-05-16 20:09:50 +00:00
self._SetShortcutString()
def _SetShortcutString( self ):
display_string = self._shortcut.ToString()
2019-11-14 03:56:30 +00:00
self.setText( display_string )
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
def keyPressEvent( self, event ):
2018-05-16 20:09:50 +00:00
shortcut = ConvertKeyEventToShortcut( event )
if shortcut is not None:
self._shortcut = shortcut
if self._related_radio is not None:
2019-11-14 03:56:30 +00:00
self._related_radio.setChecked( True )
2018-05-16 20:09:50 +00:00
self._SetShortcutString()
def GetValue( self ):
return self._shortcut
def SetValue( self, shortcut ):
self._shortcut = shortcut
self._SetShortcutString()
2019-11-14 03:56:30 +00:00
class ShortcutMouse( QW.QPushButton ):
2018-05-16 20:09:50 +00:00
def __init__( self, parent, related_radio = None ):
self._shortcut = Shortcut( CC.SHORTCUT_TYPE_MOUSE, CC.SHORTCUT_MOUSE_LEFT, [] )
self._related_radio = related_radio
2019-11-14 03:56:30 +00:00
QW.QPushButton.__init__( self, parent )
2018-05-16 20:09:50 +00:00
self._SetShortcutString()
def _SetShortcutString( self ):
display_string = self._shortcut.ToString()
2019-11-14 03:56:30 +00:00
self.setText( display_string )
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
def mousePressEvent( self, event ):
self.EventMouse( event )
def mouseDoubleClickEvent( self, event ):
self.EventMouse( event )
2018-05-16 20:09:50 +00:00
def EventMouse( self, event ):
2019-11-14 03:56:30 +00:00
self.setFocus( QC.Qt.OtherFocusReason )
2018-05-16 20:09:50 +00:00
shortcut = ConvertMouseEventToShortcut( event )
if shortcut is not None:
self._shortcut = shortcut
if self._related_radio is not None:
2019-11-14 03:56:30 +00:00
self._related_radio.setChecked( True )
2018-05-16 20:09:50 +00:00
self._SetShortcutString()
def GetValue( self ):
return self._shortcut
def SetValue( self, shortcut ):
self._shortcut = shortcut
self._SetShortcutString()
2019-06-05 19:42:39 +00:00
class ShortcutSet( HydrusSerialisable.SerialisableBaseNamed ):
2018-05-16 20:09:50 +00:00
2019-06-05 19:42:39 +00:00
SERIALISABLE_TYPE = HydrusSerialisable.SERIALISABLE_TYPE_SHORTCUT_SET
SERIALISABLE_NAME = 'Shortcut Set'
2018-05-16 20:09:50 +00:00
SERIALISABLE_VERSION = 2
def __init__( self, name ):
HydrusSerialisable.SerialisableBaseNamed.__init__( self, name )
self._shortcuts_to_commands = {}
def __iter__( self ):
2019-05-22 22:35:06 +00:00
for ( shortcut, command ) in list( self._shortcuts_to_commands.items() ):
2018-05-16 20:09:50 +00:00
yield ( shortcut, command )
def __len__( self ):
return len( self._shortcuts_to_commands )
def _GetSerialisableInfo( self ):
2019-01-09 22:59:03 +00:00
return [ ( shortcut.GetSerialisableTuple(), command.GetSerialisableTuple() ) for ( shortcut, command ) in list(self._shortcuts_to_commands.items()) ]
2018-05-16 20:09:50 +00:00
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
for ( serialisable_shortcut, serialisable_command ) in serialisable_info:
shortcut = HydrusSerialisable.CreateFromSerialisableTuple( serialisable_shortcut )
command = HydrusSerialisable.CreateFromSerialisableTuple( serialisable_command )
self._shortcuts_to_commands[ shortcut ] = command
def _UpdateSerialisableInfo( self, version, old_serialisable_info ):
if version == 1:
( serialisable_mouse_actions, serialisable_keyboard_actions ) = old_serialisable_info
shortcuts_to_commands = {}
# this never stored mouse actions, so skip
services_manager = HG.client_controller.services_manager
for ( modifier, key, ( serialisable_service_key, data ) ) in serialisable_keyboard_actions:
2019-11-14 03:56:30 +00:00
# no longer updating modifier, as that was wx legacy
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
modifiers = []
shortcut = Shortcut( CC.SHORTCUT_TYPE_KEYBOARD_ASCII, key, modifiers )
2018-05-16 20:09:50 +00:00
if serialisable_service_key is None:
command = ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_SIMPLE, data )
else:
2019-01-09 22:59:03 +00:00
service_key = bytes.fromhex( serialisable_service_key )
2018-05-16 20:09:50 +00:00
if not services_manager.ServiceExists( service_key ):
continue
action = HC.CONTENT_UPDATE_FLIP
value = data
service = services_manager.GetService( service_key )
service_type = service.GetServiceType()
if service_type in HC.TAG_SERVICES:
content_type = HC.CONTENT_TYPE_MAPPINGS
elif service_type in HC.RATINGS_SERVICES:
content_type = HC.CONTENT_TYPE_RATINGS
else:
continue
command = ClientData.ApplicationCommand( CC.APPLICATION_COMMAND_TYPE_CONTENT, ( service_key, content_type, action, value ) )
shortcuts_to_commands[ shortcut ] = command
2019-01-09 22:59:03 +00:00
new_serialisable_info = ( ( shortcut.GetSerialisableTuple(), command.GetSerialisableTuple() ) for ( shortcut, command ) in list(shortcuts_to_commands.items()) )
2018-05-16 20:09:50 +00:00
return ( 2, new_serialisable_info )
def GetCommand( self, shortcut ):
if shortcut in self._shortcuts_to_commands:
return self._shortcuts_to_commands[ shortcut ]
else:
return None
2019-06-05 19:42:39 +00:00
def GetShortcuts( self, simple_command ):
shortcuts = []
for ( shortcut, command ) in self._shortcuts_to_commands.items():
if command.GetCommandType() == CC.APPLICATION_COMMAND_TYPE_SIMPLE and command.GetData() == simple_command:
shortcuts.append( shortcut )
return shortcuts
2018-05-16 20:09:50 +00:00
def SetCommand( self, shortcut, command ):
self._shortcuts_to_commands[ shortcut ] = command
2019-06-05 19:42:39 +00:00
HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIALISABLE_TYPE_SHORTCUT_SET ] = ShortcutSet
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
class ShortcutsHandler( QC.QObject ):
2017-03-29 19:39:34 +00:00
2018-03-14 21:01:02 +00:00
def __init__( self, parent, initial_shortcuts_names = None ):
2017-03-29 19:39:34 +00:00
2019-11-14 03:56:30 +00:00
QC.QObject.__init__( self, parent )
2018-03-14 21:01:02 +00:00
if initial_shortcuts_names is None:
2017-03-29 19:39:34 +00:00
2018-03-14 21:01:02 +00:00
initial_shortcuts_names = []
2017-03-29 19:39:34 +00:00
self._parent = parent
2019-11-14 03:56:30 +00:00
self._parent.installEventFilter( self )
2018-03-14 21:01:02 +00:00
self._shortcuts_names = list( initial_shortcuts_names )
2017-03-29 19:39:34 +00:00
2018-03-14 21:01:02 +00:00
def _ProcessShortcut( self, shortcut ):
shortcut_processed = False
command = HG.client_controller.GetCommandFromShortcut( self._shortcuts_names, shortcut )
if command is not None:
command_processed = self._parent.ProcessApplicationCommand( command )
2017-03-29 19:39:34 +00:00
2018-03-14 21:01:02 +00:00
if command_processed:
shortcut_processed = True
2017-03-29 19:39:34 +00:00
2018-03-22 00:03:33 +00:00
if HG.shortcut_report_mode:
message = 'Shortcut "' + shortcut.ToString() + '" matched to command "' + command.ToString() + '" on ' + repr( self._parent ) + '.'
if command_processed:
message += ' It was processed.'
else:
message += ' It was not processed.'
HydrusData.ShowText( message )
2017-03-29 19:39:34 +00:00
2018-03-14 21:01:02 +00:00
return shortcut_processed
2017-03-29 19:39:34 +00:00
2019-11-14 03:56:30 +00:00
def eventFilter( self, watched, event ):
2018-03-22 00:03:33 +00:00
2019-11-14 03:56:30 +00:00
if event.type() == QC.QEvent.KeyPress:
2018-03-14 21:01:02 +00:00
2019-11-14 03:56:30 +00:00
shortcut = ConvertKeyEventToShortcut( event )
if shortcut is not None:
2018-03-22 00:03:33 +00:00
2019-11-14 03:56:30 +00:00
if HG.shortcut_report_mode:
2018-03-22 00:03:33 +00:00
2019-11-14 03:56:30 +00:00
message = 'Key shortcut "' + shortcut.ToString() + '" passing through ' + repr( self._parent ) + '.'
2018-03-22 00:03:33 +00:00
2019-11-14 03:56:30 +00:00
if IShouldCatchShortcutEvent( self._parent, event = event ):
message += ' I am in a state to catch it.'
else:
message += ' I am not in a state to catch it.'
2018-03-22 00:03:33 +00:00
2019-11-14 03:56:30 +00:00
HydrusData.ShowText( message )
2018-03-22 00:03:33 +00:00
2019-11-14 03:56:30 +00:00
if IShouldCatchShortcutEvent( self._parent, event = event ):
2018-03-14 21:01:02 +00:00
2019-11-14 03:56:30 +00:00
shortcut_processed = self._ProcessShortcut( shortcut )
if shortcut_processed:
return True
2018-03-14 21:01:02 +00:00
2019-11-14 03:56:30 +00:00
return False
2017-03-29 19:39:34 +00:00
2019-09-11 21:51:09 +00:00
def AddShortcuts( self, shortcut_set_name ):
2017-03-29 19:39:34 +00:00
2019-09-11 21:51:09 +00:00
if shortcut_set_name not in self._shortcuts_names:
2018-03-14 21:01:02 +00:00
2019-09-11 21:51:09 +00:00
self._shortcuts_names.append( shortcut_set_name )
2018-03-14 21:01:02 +00:00
2017-03-29 19:39:34 +00:00
2019-09-11 21:51:09 +00:00
def RemoveShortcuts( self, shortcut_set_name ):
2017-03-29 19:39:34 +00:00
2019-09-11 21:51:09 +00:00
if shortcut_set_name in self._shortcuts_names:
2017-03-29 19:39:34 +00:00
2019-09-11 21:51:09 +00:00
self._shortcuts_names.remove( shortcut_set_name )
2017-03-29 19:39:34 +00:00
2018-05-16 20:09:50 +00:00
2019-06-05 19:42:39 +00:00
class ShortcutsManager( object ):
def __init__( self, controller ):
self._controller = controller
self._shortcuts = {}
self._RefreshShortcuts()
self._controller.sub( self, 'RefreshShortcuts', 'notify_new_shortcuts_data' )
def _RefreshShortcuts( self ):
self._shortcuts = {}
all_shortcuts = HG.client_controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_SHORTCUT_SET )
for shortcuts in all_shortcuts:
self._shortcuts[ shortcuts.GetName() ] = shortcuts
def GetCommand( self, shortcuts_names, shortcut ):
for name in shortcuts_names:
if name in self._shortcuts:
command = self._shortcuts[ name ].GetCommand( shortcut )
if command is not None:
if HG.gui_report_mode:
HydrusData.ShowText( 'command matched: ' + repr( command ) )
return command
return None
def GetNamesToShortcuts( self, simple_command ):
names_to_shortcuts = {}
for ( name, shortcut_set ) in self._shortcuts.items():
shortcuts = shortcut_set.GetShortcuts( simple_command )
if len( shortcuts ) > 0:
names_to_shortcuts[ name ] = shortcuts
return names_to_shortcuts
def RefreshShortcuts( self ):
self._RefreshShortcuts()
HG.client_controller.pub( 'notify_new_shortcuts_gui' )