caron / PyQtForSoftimage

A system for hosting PyQt applications inside Softimage's interface.
29 stars 10 forks source link

Special characters in pyQt text_editors (french keyboard, french Windows 7) #10

Open snippet-nicotine opened 11 years ago

snippet-nicotine commented 11 years ago

Hello,

Inside Softimage, I can't manage to type an underscore "" in the QLineEdit (or QTextEditor) it is always replaced by 8. ( It's the same for all "Alt + " keys ) I've tried to type "azerty" to be sure I'm not in qwerty mode, and it enters correctly "azerty". If I copy/paste the "" from a text editor, it works, so it's seems to come from the keyboard mapping in pyQt. I'm putting it in issue because the problem doesn't happen in standalone, but I'm assuming that I probably did something wrong, or there's an option in pyQt to fix this!!

I'm using an azerty keyboard, and a french windows 7

csaez commented 11 years ago

I have exactly the same problem with some special symbols in my qwerty keyboard (spanish distribution), i.e. to get a hashtag symbol (#) I usually press Alt Gr + 3 but inside softimage it only work pressing Shift + 3 (and you have to do some black magic to figure that out!). In an standalone app (same python/pyqt version) everything works fine.

I guess it has something to do with softimage and his hardcoded interpretation of keys, but I don't know how to fix it :-1:

snippet-nicotine commented 11 years ago

I think it's something to change in the PyQtForSoftimage\Application\Plugins\qtevents.py There is a KEY_MAPPING, I'm making an Azerty one...

For "_" => 56: ( Qt.Key8, '', None )

caron commented 11 years ago

makes sense the mapping is problematic, softimage doesn't even support french, it supports english and japanese. if you can adjust the keymapping to work for both english and french then i will accept a change/pull request

snippet-nicotine commented 11 years ago

So I have map a french keyboard. I've made two dictionaries : ENGLISH_MAPPING and FRENCH_MAPPING. Now the indexes are no longer int but str (I found it more esay to edit with "keyCode", "alt-KeyCode", ... ) but I let the 300 + KeyCode for "shift". For French keyboard, just switch the KEYBOARD_LANGUAGE to "french"

This is my qtevents.py file:

from PyQt4.QtCore import Qt

from win32com.client import Dispatch as disp
from win32com.client import constants as C
si = disp('XSI.Application')

# Create a mapping of virtual keys
import win32con

KEYBOARD_LANGUAGE = "english"
ENGLISH_MAPPING   = {
    # key: ( Qt::Key,           ascii,  modifiers )

     " 8": ( Qt.Key_Backspace,    '',     None ),
     " 9": ( Qt.Key_Tab,          '\t',   None ),
     "13": ( Qt.Key_Enter,        '\n',   None ),
     "16": ( Qt.Key_Shift,        '',     None ),
     "17": ( Qt.Key_Control,      '',     None ),
     "18": ( Qt.Key_Alt,          '',     None ),
     "19": ( Qt.Key_Pause,        '',     None ),
     "20": ( Qt.Key_CapsLock,     '',     None ),
     "27": ( Qt.Key_Escape,       '',     None ),
     "32": ( Qt.Key_Space,        ' ',    None ),
     "33": ( Qt.Key_PageUp,       '',     None ),
     "34": ( Qt.Key_PageDown,     '',     None ),
     "35": ( Qt.Key_End,          '',     None ),
     "36": ( Qt.Key_Home,         '',     None ),
     "37": ( Qt.Key_Left,         '',     None ),
     "38": ( Qt.Key_Up,           '',     None ),
     "39": ( Qt.Key_Right,        '',     None ),
     "40": ( Qt.Key_Down,         '',     None ),
     "44": ( Qt.Key_SysReq,       '',     None ),
     "45": ( Qt.Key_Insert,       '',     None ),
     "46": ( Qt.Key_Delete,       '',     None ),
     "48": ( Qt.Key_0,            '0',    None ),
     "49": ( Qt.Key_1,            '1',    None ),
     "50": ( Qt.Key_2,            '2',    None ),
     "51": ( Qt.Key_3,            '3',    None ),
     "52": ( Qt.Key_4,            '4',    None ),
     "53": ( Qt.Key_5,            '5',    None ),
     "54": ( Qt.Key_6,            '6',    None ),
     "55": ( Qt.Key_7,            '7',    None ),
     "56": ( Qt.Key_8,            '8',    None ),
     "57": ( Qt.Key_9,            '9',    None ),
     "65": ( Qt.Key_A,            'a',    None ),
     "66": ( Qt.Key_B,            'b',    None ),
     "67": ( Qt.Key_C,            'c',    None ),
     "68": ( Qt.Key_D,            'd',    None ),
     "69": ( Qt.Key_E,            'e',    None ),
     "70": ( Qt.Key_F,            'f',    None ),
     "71": ( Qt.Key_G,            'g',    None ),
     "72": ( Qt.Key_H,            'h',    None ),
     "73": ( Qt.Key_I,            'i',    None ),
     "74": ( Qt.Key_J,            'j',    None ),
     "75": ( Qt.Key_K,            'k',    None ),
     "76": ( Qt.Key_L,            'l',    None ),
     "77": ( Qt.Key_M,            'm',    None ),
     "78": ( Qt.Key_N,            'n',    None ),
     "79": ( Qt.Key_O,            'o',    None ),
     "80": ( Qt.Key_P,            'p',    None ),
     "81": ( Qt.Key_Q,            'q',    None ),
     "82": ( Qt.Key_R,            'r',    None ),
     "83": ( Qt.Key_S,            's',    None ),
     "84": ( Qt.Key_T,            't',    None ),
     "85": ( Qt.Key_U,            'u',    None ),
     "86": ( Qt.Key_V,            'v',    None ),
     "87": ( Qt.Key_W,            'w',    None ),
     "88": ( Qt.Key_X,            'x',    None ),
     "89": ( Qt.Key_Y,            'y',    None ),
     "90": ( Qt.Key_Z,            'z',    None ),
     "93": ( Qt.Key_Print,        '',     None ),
     "96": ( Qt.Key_0,            '0',    Qt.KeypadModifier ),
     "97": ( Qt.Key_1,            '1',    Qt.KeypadModifier ),
     "98": ( Qt.Key_2,            '2',    Qt.KeypadModifier ),
     "99": ( Qt.Key_3,            '3',    Qt.KeypadModifier ),
    "100": ( Qt.Key_4,            '4',    Qt.KeypadModifier ),
    "101": ( Qt.Key_5,            '5',    Qt.KeypadModifier ),
    "102": ( Qt.Key_5,            '6',    Qt.KeypadModifier ),
    "103": ( Qt.Key_5,            '7',    Qt.KeypadModifier ),
    "104": ( Qt.Key_5,            '8',    Qt.KeypadModifier ),
    "105": ( Qt.Key_5,            '9',    Qt.KeypadModifier ),
    "106": ( Qt.Key_Asterisk,     '*',    Qt.KeypadModifier ),
    "107": ( Qt.Key_Plus,         '+',    Qt.KeypadModifier ),
    "109": ( Qt.Key_Minus,        '-',    Qt.KeypadModifier ),
    "110": ( Qt.Key_Period,       '.',    Qt.KeypadModifier ),
    "111": ( Qt.Key_Slash,        '/',    Qt.KeypadModifier ),
    "112": ( Qt.Key_F1,           '',     None ),
    "113": ( Qt.Key_F2,           '',     None ),
    "114": ( Qt.Key_F3,           '',     None ),
    "115": ( Qt.Key_F4,           '',     None ),
    "116": ( Qt.Key_F5,           '',     None ),
    "117": ( Qt.Key_F6,           '',     None ),
    "118": ( Qt.Key_F7,           '',     None ),
    "119": ( Qt.Key_F8,           '',     None ),
    "120": ( Qt.Key_F9,           '',     None ),
    "121": ( Qt.Key_F10,          '',     None ),
    "122": ( Qt.Key_F11,          '',     None ),
    "113": ( Qt.Key_F12,          '',     None ),
    "144": ( Qt.Key_NumLock,      '',     None ),
    "145": ( Qt.Key_ScrollLock,   '',     None ),
    "186": ( Qt.Key_Semicolon,    ';',    None ),
    "187": ( Qt.Key_Equal,        '=',    None ),
    "188": ( Qt.Key_Comma,        ',',    None ),
    "189": ( Qt.Key_Minus,        '-',    None ),
    "190": ( Qt.Key_Period,       '.',    None ),
    "191": ( Qt.Key_Slash,        '/',    None ),
    "192": ( Qt.Key_QuoteLeft,    '`',    None ),
    "219": ( Qt.Key_BracketLeft,  '[',    None ),
    "220": ( Qt.Key_Backslash,    '\\',   None ),
    "221": ( Qt.Key_BraceRight,   ']',    None ),
    "222": ( Qt.Key_QuoteLeft,    "'",    None ),

    # Calculate the SHIFT key as 300 + key value
    "348": ( Qt.Key_ParenRight,   ')',    None ), # Shift+0
    "349": ( Qt.Key_Exclam,       '!',    None ), # Shift+1
    "350": ( Qt.Key_At,           '@',    None ), # Shift+2
    "351": ( Qt.Key_NumberSign,   '#',    None ), # Shift+3
    "352": ( Qt.Key_Dollar,       '$',    None ), # Shift+4
    "353": ( Qt.Key_Percent,      '%',    None ), # Shift+5
    "354": ( Qt.Key_6,            '6',    None ),
    "355": ( Qt.Key_Ampersand,    '&',    None ), # Shift+7
    "356": ( Qt.Key_Asterisk,     '*',    None ), # Shift+8
    "357": ( Qt.Key_ParenLeft,    '(',    None ), # Shift+9

    "365": ( Qt.Key_A,            'A',    None ),
    "366": ( Qt.Key_B,            'B',    None ),
    "367": ( Qt.Key_C,            'C',    None ),
    "368": ( Qt.Key_D,            'D',    None ),
    "369": ( Qt.Key_E,            'E',    None ),
    "370": ( Qt.Key_F,            'F',    None ),
    "371": ( Qt.Key_G,            'G',    None ),
    "372": ( Qt.Key_H,            'H',    None ),
    "373": ( Qt.Key_I,            'I',    None ),
    "374": ( Qt.Key_J,            'J',    None ),
    "375": ( Qt.Key_K,            'K',    None ),
    "376": ( Qt.Key_L,            'L',    None ),
    "377": ( Qt.Key_M,            'M',    None ),
    "378": ( Qt.Key_N,            'N',    None ),
    "379": ( Qt.Key_O,            'O',    None ),
    "380": ( Qt.Key_P,            'P',    None ),
    "381": ( Qt.Key_Q,            'Q',    None ),
    "382": ( Qt.Key_R,            'R',    None ),
    "383": ( Qt.Key_S,            'S',    None ),
    "384": ( Qt.Key_T,            'T',    None ),
    "385": ( Qt.Key_U,            'U',    None ),
    "386": ( Qt.Key_V,            'V',    None ),
    "387": ( Qt.Key_W,            'W',    None ),
    "388": ( Qt.Key_X,            'X',    None ),
    "389": ( Qt.Key_Y,            'Y',    None ),
    "390": ( Qt.Key_Z,            'Z',    None ),

    "486": ( Qt.Key_Colon,        ':',    None ), # Shift+;
    "487": ( Qt.Key_Plus,         '+',    None ), # Shift++
    "488": ( Qt.Key_Less,         '<',    None ), # Shift+,
    "489": ( Qt.Key_Underscore,   '_',    None ), # Shift+-
    "490": ( Qt.Key_Greater,      '>',    None ), # Shift+>
    "491": ( Qt.Key_Question,     '?',    None ), # Shift+?
    "492": ( Qt.Key_AsciiTilde,   '~',    None ), # Shift+`
    "519": ( Qt.Key_BraceLeft,    '{',    None ), # Shift+[
    "520": ( Qt.Key_Bar,          '|',    None ), # Shift+\
    "521": ( Qt.Key_BraceRight,   '}',    None ), # Shift+]
    "522": ( Qt.Key_QuoteDbl,     '"',    None ), # Shift+'
}
FRENCH_MAPPING   = {
    # key: ( Qt::Key,           ascii,  modifiers )
      "8":     ( Qt.Key_Backspace,             '',     None ),
      "9":     ( Qt.Key_Tab,                   '\t',   None ),
     "13":     ( Qt.Key_Enter,                 '\n',   None ),
     "16":     ( Qt.Key_Shift,                 '',     None ),
     "17":     ( Qt.Key_Control,               '',     None ),
     "18":     ( Qt.Key_Alt,                   '',     None ),
     "19":     ( Qt.Key_Pause,                 '',     None ),
     "20":     ( Qt.Key_CapsLock,              '',     None ),
     "27":     ( Qt.Key_Escape,                '',     None ),
     "32":     ( Qt.Key_Space,                ' ',     None ),
     "33":     ( Qt.Key_PageUp,                '',     None ),
     "34":     ( Qt.Key_PageDown,              '',     None ),
     "35":     ( Qt.Key_End,                   '',     None ),
     "36":     ( Qt.Key_Home,                  '',     None ),
     "37":     ( Qt.Key_Left,                  '',     None ),
     "38":     ( Qt.Key_Up,                    '',     None ),
     "39":     ( Qt.Key_Right,                 '',     None ),
     "40":     ( Qt.Key_Down,                  '',     None ),
     "44":     ( Qt.Key_SysReq,                '',     None ),
     "45":     ( Qt.Key_Insert,                '',     None ),
     "46":     ( Qt.Key_Delete,                '',     None ),
     "48":     ( Qt.Key_0,                   u'à',     None ),
     "alt-48": ( Qt.Key_At,                   '@',     None ),
     "49":     ( Qt.Key_Ampersand,            '&',     None ),
     "50":     ( Qt.Key_2,                   u'é',     None ),
     "alt-50": ( Qt.Key_AsciiTilde,           '~',     None ),
     "51":     ( Qt.Key_QuoteDbl,             '"',     None ),
     "alt-51": ( Qt.Key_NumberSign,           '#',     None ),
     "52":     ( Qt.Key_QuoteLeft,            "'",     None ),
     "alt-52": ( Qt.Key_BraceLeft,            "{",     None ),
     "53":     ( Qt.Key_ParenLeft,            '(',     None ),
     "alt-53": ( Qt.Key_BracketLeft,          '[',     None ), 
     "54":     ( Qt.Key_Minus,                '-',     None ),
     "alt-54": ( Qt.Key_Bar,                  '|',     None ),
     "55":     ( Qt.Key_7,                   u'è',    None ),
     "56":     ( Qt.Key_Underscore,           '_',    None ),
     "alt-56": ( Qt.Key_Backslash,           '\\',    None ),
     "57":     ( Qt.Key_9,                   u'ç',    None ),
     "alt-57": ( Qt.Key_unknown,             u'^',    None ),
     "65":     ( Qt.Key_A,                    'a',    None ),
     "66":     ( Qt.Key_B,                    'b',    None ),
     "67":     ( Qt.Key_C,                    'c',    None ),
     "68":     ( Qt.Key_D,                    'd',    None ),
     "69":     ( Qt.Key_E,                    'e',    None ),
     "70":     ( Qt.Key_F,                    'f',    None ),
     "71":     ( Qt.Key_G,                    'g',    None ),
     "72":     ( Qt.Key_H,                    'h',    None ),
     "73":     ( Qt.Key_I,                    'i',    None ),
     "74":     ( Qt.Key_J,                    'j',    None ),
     "75":     ( Qt.Key_K,                    'k',    None ),
     "76":     ( Qt.Key_L,                    'l',    None ),
     "77":     ( Qt.Key_M,                    'm',    None ),
     "78":     ( Qt.Key_N,                    'n',    None ),
     "79":     ( Qt.Key_O,                    'o',    None ),
     "80":     ( Qt.Key_P,                    'p',    None ),
     "81":     ( Qt.Key_Q,                    'q',    None ),
     "82":     ( Qt.Key_R,                    'r',    None ),
     "83":     ( Qt.Key_S,                    's',    None ),
     "84":     ( Qt.Key_T,                    't',    None ),
     "85":     ( Qt.Key_U,                    'u',    None ),
     "86":     ( Qt.Key_V,                    'v',    None ),
     "87":     ( Qt.Key_W,                    'w',    None ),
     "88":     ( Qt.Key_X,                    'x',    None ),
     "89":     ( Qt.Key_Y,                    'y',    None ),
     "90":     ( Qt.Key_Z,                    'z',    None ),
     "93":     ( Qt.Key_Print,                '',     None ),
     "96":     ( Qt.Key_0,                    '0',    Qt.KeypadModifier ),
     "97":     ( Qt.Key_1,                    '1',    Qt.KeypadModifier ),
     "98":     ( Qt.Key_2,                    '2',    Qt.KeypadModifier ),
     "99":     ( Qt.Key_3,                    '3',    Qt.KeypadModifier ),
    "100":     ( Qt.Key_4,                    '4',    Qt.KeypadModifier ),
    "101":     ( Qt.Key_5,                    '5',    Qt.KeypadModifier ),
    "102":     ( Qt.Key_5,                    '6',    Qt.KeypadModifier ),
    "103":     ( Qt.Key_5,                    '7',    Qt.KeypadModifier ),
    "104":     ( Qt.Key_5,                    '8',    Qt.KeypadModifier ),
    "105":     ( Qt.Key_5,                    '9',    Qt.KeypadModifier ),
    "106":     ( Qt.Key_Asterisk,             '*',    Qt.KeypadModifier ),
    "107":     ( Qt.Key_Plus,                 '+',    Qt.KeypadModifier ),
    "109":     ( Qt.Key_Minus,                '-',    Qt.KeypadModifier ),
    "110":     ( Qt.Key_Period,               '.',    Qt.KeypadModifier ),
    "111":     ( Qt.Key_Slash,                '/',    Qt.KeypadModifier ),
    "112":     ( Qt.Key_F1,                   '',     None ),
    "113":     ( Qt.Key_F2,                   '',     None ),
    "114":     ( Qt.Key_F3,                   '',     None ),
    "115":     ( Qt.Key_F4,                   '',     None ),
    "116":     ( Qt.Key_F5,                   '',     None ),
    "117":     ( Qt.Key_F6,                   '',     None ),
    "118":     ( Qt.Key_F7,                   '',     None ),
    "119":     ( Qt.Key_F8,                   '',     None ),
    "120":     ( Qt.Key_F9,                   '',     None ),
    "121":     ( Qt.Key_F10,                  '',     None ),
    "122":     ( Qt.Key_F11,                  '',     None ),
    "113":     ( Qt.Key_F12,                  '',     None ),
    "144":     ( Qt.Key_NumLock,              '',     None ),
    "145":     ( Qt.Key_ScrollLock,           '',     None ),
    "186":     ( Qt.Key_Dollar,              '$',    None ),
    "alt-186": ( Qt.Key_Dollar,             u'¤',    None ),
    "187":     ( Qt.Key_Equal,               '=',    None ),
    "alt-187": ( Qt.Key_BraceRight,          '}',    None ),
    "188":     ( Qt.Key_Comma,               ',',    None ),
    "189":     ( Qt.Key_Minus,               '-',    None ),
    "190":     ( Qt.Key_Period,              ';',    None ),
    "191":     ( Qt.Key_Colon,               ':',    None ),
    "192":     ( Qt.Key_Asterisk,           u'ù',    None ),
    "219":     ( Qt.Key_ParenRight,          ')',    None ),
    "alt-219": ( Qt.Key_BracketRight,        ']',    None ),
    "220":     ( Qt.Key_Asterisk,            '*',   None ),
    "221":     ( Qt.Key_BracketRight,        ']',    None ),
    "222":     ( Qt.Key_unknown,            u"²",    None ),
    "223":     ( Qt.Key_Exclam,              "!",    None ),
    "226":     ( Qt.Key_Less,                "<",    None ),

    # Calculate the SHIFT key as 300 + key value
    "348": ( Qt.Key_ParenRight,   '0',    None ), # Shift+0
    "349": ( Qt.Key_Exclam,       '1',    None ), # Shift+1
    "350": ( Qt.Key_At,           '2',    None ), # Shift+2
    "351": ( Qt.Key_NumberSign,   '3',    None ), # Shift+3
    "352": ( Qt.Key_Dollar,       '4',    None ), # Shift+4
    "353": ( Qt.Key_Percent,      '5',    None ), # Shift+5
    "354": ( Qt.Key_6,            '6',    None ),
    "355": ( Qt.Key_Ampersand,    '7',    None ), # Shift+7
    "356": ( Qt.Key_Asterisk,     '8',    None ), # Shift+8
    "357": ( Qt.Key_ParenLeft,    '9',    None ), # Shift+9

    "365": ( Qt.Key_A,            'A',    None ),
    "366": ( Qt.Key_B,            'B',    None ),
    "367": ( Qt.Key_C,            'C',    None ),
    "368": ( Qt.Key_D,            'D',    None ),
    "369": ( Qt.Key_E,            'E',    None ),
    "370": ( Qt.Key_F,            'F',    None ),
    "371": ( Qt.Key_G,            'G',    None ),
    "372": ( Qt.Key_H,            'H',    None ),
    "373": ( Qt.Key_I,            'I',    None ),
    "374": ( Qt.Key_J,            'J',    None ),
    "375": ( Qt.Key_K,            'K',    None ),
    "376": ( Qt.Key_L,            'L',    None ),
    "377": ( Qt.Key_M,            'M',    None ),
    "378": ( Qt.Key_N,            'N',    None ),
    "379": ( Qt.Key_O,            'O',    None ),
    "380": ( Qt.Key_P,            'P',    None ),
    "381": ( Qt.Key_Q,            'Q',    None ),
    "382": ( Qt.Key_R,            'R',    None ),
    "383": ( Qt.Key_S,            'S',    None ),
    "384": ( Qt.Key_T,            'T',    None ),
    "385": ( Qt.Key_U,            'U',    None ),
    "386": ( Qt.Key_V,            'V',    None ),
    "387": ( Qt.Key_W,            'W',    None ),
    "388": ( Qt.Key_X,            'X',    None ),
    "389": ( Qt.Key_Y,            'Y',    None ),
    "390": ( Qt.Key_Z,            'Z',    None ),

    "486": ( Qt.Key_Dollar,       u'£',    None ), # Shift+;
    "487": ( Qt.Key_Plus,          '+',    None ), # Shift++
    "488": ( Qt.Key_Question,      '?',    None ), # Shift+,
    "489": ( Qt.Key_Underscore,    '_',    None ), # Shift+-
    "490": ( Qt.Key_Period,        '.',    None ), # Shift+>
    "491": ( Qt.Key_Slash,         '/',    None ), # Shift+?
    "492": ( Qt.Key_Percent,       '%',    None ), # Shift+`
    "519": ( Qt.Key_ParenRight,   u'°',    None ), # Shift+[
    "520": ( Qt.Key_Asterisk,      u'µ',    None ), # Shift+\
    "521": ( Qt.Key_unknown,      u'¨',    None ), # Shift+]
    "522": ( Qt.Key_QuoteDbl,      '"',    None ), # Shift+'
    "523": ( Qt.Key_unknown,      u'§',    None ),
    "526": ( Qt.Key_Greater,       '>',    None )
}

KEY_MAPPING = {
                "english" : ENGLISH_MAPPING,
                "french"  : FRENCH_MAPPING
                }

def consumeKey( ctxt, pressed ):
    """
    build the proper QKeyEvent from Softimage key event and send the it along to the focused widget
    """
    kcode = ctxt.GetAttribute( 'KeyCode' )
    mask = ctxt.GetAttribute( 'ShiftMask' )

    # Build the modifiers
    modifier = Qt.NoModifier
    modifierMask = ""
    if ( mask & C.siShiftMask ):
        if ( str(kcode + 300) in KEY_MAPPING[KEYBOARD_LANGUAGE] ):
            kcode += 300

        modifier |= Qt.ShiftModifier
        modifierMask = ""

    if ( mask & C.siCtrlMask ):
        modifier |= Qt.ControlModifier
        modifierMask = "control-"

    if ( mask & C.siAltMask ):        
        modifier    |= Qt.AltModifier
        modifierMask = "alt-"

    # Generate a Qt Key Event to be processed
    result  = KEY_MAPPING[KEYBOARD_LANGUAGE].get( modifierMask + str(kcode) )
    if ( result ):
        from PyQt4.QtGui import QApplication, QKeyEvent

        if ( pressed ):
            event = QKeyEvent.KeyPress
        else:
            event = QKeyEvent.KeyRelease

        if ( result[2] ):
            modifier |= result[2]

        # Send the event along to the focused widget
        QApplication.sendEvent( QApplication.instance().focusWidget(), QKeyEvent( event, result[0], modifier, result[1] ) )

def isFocusWidget():
    """
    return true if the global qApp has any focused widgets
    """
    from PyQt4.QtGui import QApplication, QCursor

    focus = False
    if QApplication.instance():
        if QApplication.instance().focusWidget():
            window = QApplication.instance().focusWidget().window()
            geom = window.geometry()
            focus = geom.contains( QCursor.pos() )

    return focus

def xsi_version():
    """
    Calculate the version number from the string.
    """
    import re
    value = 7.0
    results = re.match(r"[^\d]*\.?(\d+)\.(\d+)", si.Version())
    if results:
        value = float('.'.join(results.groups()))
    else:
        print 'Softmage version is unknown!'
    del re
    return value

# Softimage plugin registration
def XSILoadPlugin( in_reg ):
    in_reg.Author = "Steven Caron"  
    in_reg.Name = "QtEvents"
    in_reg.Major = 0
    in_reg.Minor = 1

    import sys
    path = in_reg.OriginPath
    if path not in sys.path:
        sys.path.append( path )

    in_reg.RegisterEvent( "QtEvents_KeyDown", C.siOnKeyDown )
    in_reg.RegisterEvent( "QtEvents_KeyUp", C.siOnKeyUp )

    # register all potential events
    in_reg.RegisterEvent( "QtEvents_Activate", C.siOnActivate )

    in_reg.RegisterEvent( "QtEvents_FileExport", C.siOnEndFileExport )
    in_reg.RegisterEvent( "QtEvents_FileImport", C.siOnEndFileImport )
    #in_reg.RegisterEvent( "QtEvents_CustomFileExport", C.siOnCustomFileExport )
    #in_reg.RegisterEvent( "QtEvents_CustomFileImport", C.siOnCustomFileImport )

    in_reg.RegisterEvent( "QtEvents_RenderFrame", C.siOnEndFrame )
    in_reg.RegisterEvent( "QtEvents_RenderSequence", C.siOnEndSequence )
    # siOnRenderAbort added in 2012?, err v10.0
    #if xsi_version() >= 10.0:
        #in_reg.RegisterEvent( "QtEvents_RenderAbort", C.siOnRenderAbort )
    in_reg.RegisterEvent( "QtEvents_PassChange", C.siOnEndPassChange )

    in_reg.RegisterEvent( "QtEvents_SceneOpen", C.siOnEndSceneOpen )
    in_reg.RegisterEvent( "QtEvents_SceneSaveAs", C.siOnEndSceneSaveAs )
    in_reg.RegisterEvent( "QtEvents_SceneSave", C.siOnEndSceneSave2 )
    in_reg.RegisterEvent( "QtEvents_ChangeProject", C.siOnChangeProject )

    # events added in 2011, err v9.0
    if xsi_version() >= 9.0:
        in_reg.RegisterEvent( "QtEvents_ConnectShader", C.siOnConnectShader )
        in_reg.RegisterEvent( "QtEvents_DisconnectShader", C.siOnDisconnectShader )
        in_reg.RegisterEvent( "QtEvents_CreateShader", C.siOnCreateShader )

    in_reg.RegisterEvent( "QtEvents_SourcePathChange", C.siOnSourcePathChange )

    # the following have a high potential to be expensive/slow
    in_reg.RegisterEvent( "QtEvents_DragAndDrop", C.siOnDragAndDrop )
    in_reg.RegisterEvent( "QtEvents_ObjectAdded", C.siOnObjectAdded )
    in_reg.RegisterEvent( "QtEvents_ObjectRemoved", C.siOnObjectRemoved )
    in_reg.RegisterEvent( "QtEvents_SelectionChange", C.siOnSelectionChange )
    in_reg.RegisterEvent( "QtEvents_ValueChange", C.siOnValueChange )

    # mute immediately. the dialog is responsble for turning the events it needs on
    events = si.EventInfos
    from sisignals import EVENT_MAPPING
    for key,value in EVENT_MAPPING.iteritems():
        event = events( value )
        if si.ClassName( event ) == "EventInfo":
            event.Mute = True

    return True

def XSIUnloadPlugin( in_reg ):
    si.LogMessage( in_reg.Name + " has been unloaded.",C.siVerbose)
    return True

def QtEvents_KeyDown_OnEvent( in_ctxt ):
    # Block XSI keys from processing, pass along to Qt
    if isFocusWidget():
        consumeKey( in_ctxt, True )

        # Block the Signal from XSI
        in_ctxt.SetAttribute( 'Consumed', True )

    return True

def QtEvents_KeyUp_OnEvent( in_ctxt ):
    # Block XSI keys from processing, pass along to Qt
    if isFocusWidget():
        consumeKey( in_ctxt, False )

        # Block the Signal from XSI
        in_ctxt.SetAttribute( 'Consumed', True )

    return True

def QtEvents_Activate_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siActivate.emit( in_ctxt.GetAttribute( "State" ) )

def QtEvents_FileExport_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siFileExport.emit( in_ctxt.GetAttribute( "FileName" ) )

def QtEvents_FileImport_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siFileImport.emit( in_ctxt.GetAttribute( "FileName" ) )

#def QtEvents_CustomFileExport_OnEvent( in_ctxt ):

#def QtEvents_CustomFileImport_OnEvent( in_ctxt ):

def QtEvents_RenderFrame_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siRenderFrame.emit( in_ctxt.GetAttribute( "FileName" ), in_ctxt.GetAttribute( "Frame" ) )

def QtEvents_RenderSequence_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siRenderSequence.emit( in_ctxt.GetAttribute( "FileName" ), in_ctxt.GetAttribute( "Frame" ) )

def QtEvents_RenderAbort_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siRenderAbort.emit( in_ctxt.GetAttribute( "FileName" ), in_ctxt.GetAttribute( "Frame" ) )

def QtEvents_PassChange_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siPassChange.emit( in_ctxt.GetAttribute( "TargetPass" ) )

def QtEvents_SceneOpen_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siSceneOpen.emit( in_ctxt.GetAttribute( "FileName" ) )

def QtEvents_SceneSaveAs_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siSceneSaveAs.emit( in_ctxt.GetAttribute( "FileName" ) )

def QtEvents_SceneSave_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siSceneSave.emit( in_ctxt.GetAttribute( "FileName" ) )

def QtEvents_ChangeProject_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siChangeProject.emit( in_ctxt.GetAttribute( "NewProjectPath" ) )

def QtEvents_ConnectShader_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siConnectShader.emit( in_ctxt.GetAttribute( "Source" ), in_ctxt.GetAttribute( "Target" ) )

def QtEvents_DisconnectShader_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siDisconnectShader.emit( in_ctxt.GetAttribute( "Source" ), in_ctxt.GetAttribute( "Target" ) )

def QtEvents_CreateShader_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siCreateShader.emit( in_ctxt.GetAttribute( "Shader" ), in_ctxt.GetAttribute( "ProgID" ) )

def QtEvents_SourcePathChange_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siSourcePathChange.emit( in_ctxt.GetAttribute( "FileName" ) )

def QtEvents_DragAndDrop_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siDragAndDrop.emit( in_ctxt.GetAttribute( "DragSource" ) )

def QtEvents_ObjectAdded_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siObjectAdded.emit( in_ctxt.GetAttribute( "Objects" ) )

def QtEvents_ObjectRemoved_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siObjectRemoved.emit( in_ctxt.GetAttribute( "Objects" ) )

def QtEvents_SelectionChange_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siSelectionChange.emit( in_ctxt.GetAttribute( "ChangeType" ) )

def QtEvents_ValueChange_OnEvent( in_ctxt ):
    from sisignals import signals
    signals.siValueChange.emit( in_ctxt.GetAttribute( "FullName" ) )
caron commented 11 years ago

thanks for the code, we will need to evaluate if this is something we should support. i also need to test it in an english only keyboard environment.

lastly, cesar, if he could make his own for spanish using this code as a guide we might have better language/keyboard support :)

so you confirm this is working for you?

csaez commented 11 years ago

Sure, I can work on a template and share it.

But... what do you think about read the keyboard layout via win32api.GetKeyboardLayout() (dunno about linux, it's already supported?) and dinamically get the right mapping template from an external file (json, pickle or any other i/o module). Or maybe we could add a softimage preference to set the language and keep it simple.

I dont know, add a new template in the middle of the logic/code doesn't feels right to me, maybe there's a better way.

caron commented 11 years ago

I dont know, add a new template in the middle of the logic/code doesn't feels right to me, maybe there's a better way.

exactly, that is not why i am just including the linked code. your suggestions sound more like what i want. we need to consider how a user would configure this, if they need to at all.

i guess i was suggesting to you if you could add your own keycodes to test if this works around the issue, a long term cleaner solution is definitely what we all want.

snippet-nicotine commented 11 years ago

Sure this is not the best way to do! This code was more for helping making a new keyboard template. I thought that steven was more able to deal with the plugin architecture. (externalise mappings and integrate user_preferences)

caron commented 11 years ago

your code is very welcome and proves we have work to do in order to make it more language compliant. i am glad we can agree this isn't the preferred method going forwards.

i don't know when i will have time to work on it, but in the mean time you have a workaround, correct?

snippet-nicotine commented 11 years ago

yes this code is my workaround, so there is no emergency!!

caron commented 11 years ago

here is some reference for future development... http://hektor.umcs.lublin.pl/~mikosmul/computing/articles/custom-keyboard-layouts-xkb.html http://msdn.microsoft.com/en-us/goglobal/bb964665.aspx