Export to GitHub

pymt - issue #277

MTVKeyboard - add_custom_layout doesn't work


Posted on Jul 4, 2010 by Grumpy Monkey

What steps will reproduce the problem? 1. Create your own KeyboardLayout. 2. Add it with add_custom_layout(Layout()) 3. Start the Keyboard with MTVKeyboard(layout = 'Layout.ID')

What is the expected output? The Keyboard with my layout. What do you see instead? Traceback (most recent call last): File "start.py", line 91, in <module> pymt.runTouchApp(baseWidget)
File "/usr/lib/python2.6/site-packages/pymt/base.py", line 352, in runTouchApp pymt_window.mainloop() File "/usr/lib/python2.6/site-packages/pymt/ui/window/win_pygame.py", line 124, in mainloop evloop.idle() File "/usr/lib/python2.6/site-packages/pymt/base.py", line 201, in idle pymt_window.dispatch_event('on_draw') File "/usr/lib/python2.6/site-packages/pymt/event.py", line 344, in dispatch_event if func(*args): File "/usr/lib/python2.6/site-packages/pymt/ui/window/init.py", line 355, in on_draw w.dispatch_event('on_draw') File "/usr/lib/python2.6/site-packages/pymt/event.py", line 344, in dispatch_event if func(*args): File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/widget.py", line 360, in on_draw w.dispatch_event('on_draw') File "/usr/lib/python2.6/site-packages/pymt/event.py", line 344, in dispatch_event if func(*args): File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/scatter.py", line 141, in on_draw super(MTScatterWidget, self).on_draw() File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/widget.py", line 357, in on_draw self.draw() File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/composed/vkeyboard.py", line 433, in draw self._update() File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/composed/vkeyboard.py", line 335, in _update layoutmode = '%s:%s' % (self.layout.ID, self.mode) AttributeError: 'str' object has no attribute 'ID'

What version of the product are you using? On what operating system? I use PyMT 0.4 but I saw the bug in the git too. I use Archlinux

Please provide any additional information below. This error came because of this line in pymt/ui/widgets/composed/vkeyboard.py self.layout = kwargs.get('layout') You shuffle things because you use the same variable for the object and the id for the layout. Replace: # read default layout in configuration if self.layout is None: idlayout = pymt.pymt_config.get('keyboard', 'layout') # search layout for layout in MTVKeyboard.available_layout: if layout.ID == idlayout: self.layout = layout() break # no layout found ? if self.layout is None: pymt.pymt_logger.warning('Vkeyboard: Keyboard layout <%s> not found, fallback on QWERTY' % idlayout) self.layout = KeyboardLayoutQWERTY() With: layout_id = self.layout self.layout = None

    # read default layout in configuration
    if layout_id == None:
        layout_id = pymt.pymt_config.get('keyboard', 'layout')
    # search layout
    for layout in MTVKeyboard.available_layout:
        if layout.ID == layout_id:
            self.layout = layout
            break
    # no layout found ?
    if self.layout == None:
        pymt.pymt_logger.warning('Vkeyboard: Keyboard layout &lt;%s&gt; not found, fallback on QWERTY' % layout_id)
        self.layout = KeyboardLayoutQWERTY()

And you will see that it works.

Comment #1

Posted on Jul 4, 2010 by Quick Bird

Thanks for reporting the bug!

Can I get the layout to test it?

Comment #2

Posted on Jul 4, 2010 by Grumpy Monkey

I copied one of the standard layouts and changed only the header information. Here is it: class KeyboardLayoutQWERTZ(KeyboardLayout): '''Implementation of QWERTZ Layout''' ID = 'qwertz' TITLE = 'Qwertz' DESCRIPTION = 'A classical German Keyboard' # Need to be comment out because I don't defined kbdlayout_default_font #FONT_FILENAME = kbdlayout_default_font NORMAL_1 = [ ('~', '~', None, 1), ('!', '!', None, 1), ('@', '@', None, 1), ('#', '#', None, 1), ('$', '$', None, 1), ('%', '%', None, 1), ('^', '^', None, 1), ('&', '&', None, 1), ('', '', None, 1), ('(', '(', None, 1), (')', ')', None, 1), ('', '', None, 1), ('+', '+', None, 1), (u'\u232b', None, 'backspace', 2), ] NORMAL_2 = [ (u'\u21B9', chr(0x09), None, 1.5), ('q', 'q', None, 1), ('w', 'w', None, 1), ('e', 'e', None, 1), ('r', 'r', None, 1), ('t', 't', None, 1), ('y', 'y', None, 1), ('u', 'u', None, 1), ('i', 'i', None, 1), ('o', 'o', None, 1), ('p', 'p', None, 1), ('{', '{', None, 1), ('}', '}', None, 1), ('|', '|', None, 1.5) ] NORMAL_3 = [ (u'\u21ea', None, 'capslock', 1.8), ('a', 'a', None, 1), ('s', 's', None, 1), ('d', 'd', None, 1), ('f', 'f', None, 1), ('g', 'g', None, 1), ('h', 'h', None, 1), ('j', 'j', None, 1), ('k', 'k', None, 1), ('l', 'l', None, 1), (':', ':', None, 1), ('"', '"', None, 1), (u'\u23ce', None, 'enter', 2.2), ] NORMAL_4 = [ (u'\u21e7', None, 'shift_L', 2.5), ('z', 'z', None, 1), ('x', 'x', None, 1), ('c', 'c', None, 1), ('v', 'v', None, 1), ('b', 'b', None, 1), ('n', 'n', None, 1), ('m', 'm', None, 1), ('<', '<', None, 1), ('>', '>', None, 1), ('?', '?', None, 1), (u'\u21e7', None, 'shift_R', 2.5), ] NORMAL_5 = [ ('', ' ', None, 12), (u'\u2b12', None, 'layout', 1.5), (u'\u2a2f', None, 'escape', 1.5),

]
SHIFT_1 = [
    ('`', '`', None, 1),    ('1', '1', None, 1),    ('2', '2', None, 1),
    ('3', '3', None, 1),    ('4', '4', None, 1),    ('5', '5', None, 1),
    ('6', '6', None, 1),    ('7', '7', None, 1),    ('8', '8', None, 1),
    ('9', '9', None, 1),    ('0', '0', None, 1),    ('+', '+', None, 1),
    ('=', '=', None, 1),    (u'\u232b', None, 'backspace', 2),
]
SHIFT_2 = [
    (u'\u21B9', chr(0x09), None, 1.5),  ('Q', 'Q', None, 1),    ('W', 'W', None, 1),
    ('E', 'E', None, 1),    ('R', 'R', None, 1),    ('T', 'T', None, 1),
    ('Y', 'Y', None, 1),    ('U', 'U', None, 1),    ('I', 'I', None, 1),
    ('O', 'O', None, 1),    ('P', 'P', None, 1),    ('[', '[', None, 1),
    (']', ']', None, 1),    ('?', '?', None, 1.5)
]
SHIFT_3 = [
    (u'\u21ea', None, 'capslock', 1.8),  ('A', 'A', None, 1),    ('S', 'S', None, 1),
    ('D', 'D', None, 1),    ('F', 'F', None, 1),    ('G', 'G', None, 1),
    ('H', 'H', None, 1),    ('J', 'J', None, 1),    ('K', 'K', None, 1),
    ('L', 'L', None, 1),    (':', ':', None, 1),    ('"', '"', None, 1),
    (u'\u23ce', None, 'enter', 2.2),
]
SHIFT_4 = [
    (u'\u21e7', None, 'shift_L', 2.5),  ('Z', 'Z', None, 1),    ('X', 'X', None, 1),
    ('C', 'C', None, 1),    ('V', 'V', None, 1),    ('B', 'B', None, 1),
    ('N', 'N', None, 1),    ('M', 'M', None, 1),    (',', ',', None, 1),
    ('.', '.', None, 1),    ('/', '/', None, 1),    (u'\u21e7', None, 'shift_R', 2.5),
]
SHIFT_5 = [
    ('', ' ', None, 12), (u'\u2b12', None, 'layout', 1.5), (u'\u2a2f', None, 'escape', 1.5),
]

Comment #3

Posted on Jul 4, 2010 by Quick Bird

Sorry, I forgot to ask you for the code that you were using to add your own layout. Can you paste it as well please?

Comment #4

Posted on Jul 4, 2010 by Grumpy Monkey

Here is the whole code I used:

!/usr/bin/env python

from pymt import *

class BaseWidget(MTWidget): def init(self): MTWidget.init(self)

class KeyboardLayoutQWERTZ(KeyboardLayout): '''Implementation of QWERTZ Layout''' ID = 'qwertz' TITLE = 'Qwertz' DESCRIPTION = 'A classical German Keyboard' #FONT_FILENAME = kbdlayout_default_font NORMAL_1 = [ ('~', '~', None, 1), ('!', '!', None, 1), ('@', '@', None, 1), ('#', '#', None, 1), ('$', '$', None, 1), ('%', '%', None, 1), ('^', '^', None, 1), ('&', '&', None, 1), ('', '', None, 1), ('(', '(', None, 1), (')', ')', None, 1), ('', '', None, 1), ('+', '+', None, 1), (u'\u232b', None, 'backspace', 2), ] NORMAL_2 = [ (u'\u21B9', chr(0x09), None, 1.5), ('q', 'q', None, 1), ('w', 'w', None, 1), ('e', 'e', None, 1), ('r', 'r', None, 1), ('t', 't', None, 1), ('y', 'y', None, 1), ('u', 'u', None, 1), ('i', 'i', None, 1), ('o', 'o', None, 1), ('p', 'p', None, 1), ('{', '{', None, 1), ('}', '}', None, 1), ('|', '|', None, 1.5) ] NORMAL_3 = [ (u'\u21ea', None, 'capslock', 1.8), ('a', 'a', None, 1), ('s', 's', None, 1), ('d', 'd', None, 1), ('f', 'f', None, 1), ('g', 'g', None, 1), ('h', 'h', None, 1), ('j', 'j', None, 1), ('k', 'k', None, 1), ('l', 'l', None, 1), (':', ':', None, 1), ('"', '"', None, 1), (u'\u23ce', None, 'enter', 2.2), ] NORMAL_4 = [ (u'\u21e7', None, 'shift_L', 2.5), ('z', 'z', None, 1), ('x', 'x', None, 1), ('c', 'c', None, 1), ('v', 'v', None, 1), ('b', 'b', None, 1), ('n', 'n', None, 1), ('m', 'm', None, 1), ('<', '<', None, 1), ('>', '>', None, 1), ('?', '?', None, 1), (u'\u21e7', None, 'shift_R', 2.5), ] NORMAL_5 = [ ('', ' ', None, 12), (u'\u2b12', None, 'layout', 1.5), (u'\u2a2f', None, 'escape', 1.5),

]
SHIFT_1 = [
    ('`', '`', None, 1),    ('1', '1', None, 1),    ('2', '2', None, 1),
    ('3', '3', None, 1),    ('4', '4', None, 1),    ('5', '5', None, 1),
    ('6', '6', None, 1),    ('7', '7', None, 1),    ('8', '8', None, 1),
    ('9', '9', None, 1),    ('0', '0', None, 1),    ('+', '+', None, 1),
    ('=', '=', None, 1),    (u'\u232b', None, 'backspace', 2),
]
SHIFT_2 = [
    (u'\u21B9', chr(0x09), None, 1.5),  ('Q', 'Q', None, 1),    ('W', 'W', None, 1),
    ('E', 'E', None, 1),    ('R', 'R', None, 1),    ('T', 'T', None, 1),
    ('Y', 'Y', None, 1),    ('U', 'U', None, 1),    ('I', 'I', None, 1),
    ('O', 'O', None, 1),    ('P', 'P', None, 1),    ('[', '[', None, 1),
    (']', ']', None, 1),    ('?', '?', None, 1.5)
]
SHIFT_3 = [
    (u'\u21ea', None, 'capslock', 1.8),  ('A', 'A', None, 1),    ('S', 'S', None, 1),
    ('D', 'D', None, 1),    ('F', 'F', None, 1),    ('G', 'G', None, 1),
    ('H', 'H', None, 1),    ('J', 'J', None, 1),    ('K', 'K', None, 1),
    ('L', 'L', None, 1),    (':', ':', None, 1),    ('"', '"', None, 1),
    (u'\u23ce', None, 'enter', 2.2),
]
SHIFT_4 = [
    (u'\u21e7', None, 'shift_L', 2.5),  ('Z', 'Z', None, 1),    ('X', 'X', None, 1),
    ('C', 'C', None, 1),    ('V', 'V', None, 1),    ('B', 'B', None, 1),
    ('N', 'N', None, 1),    ('M', 'M', None, 1),    (',', ',', None, 1),
    ('.', '.', None, 1),    ('/', '/', None, 1),    (u'\u21e7', None, 'shift_R', 2.5),
]
SHIFT_5 = [
    ('', ' ', None, 12), (u'\u2b12', None, 'layout', 1.5), (u'\u2a2f', None, 'escape', 1.5),
]

if name == 'main': main_window = getWindow() main_widget = BaseWidget()

MTVKeyboard.add_custom_layout(KeyboardLayoutQWERTZ())
keyboard = MTVKeyboard(layout = 'qwertz')

main_widget.add_widget(MTScatterWidget())
main_widget.add_widget(keyboard)

runTouchApp(main_widget)

I have detected an other bug when you use add_custom_layout. Try this code and then fix the bug with the code I gave you. Now you custom layout works but then try to change the layout to QWERTY. This works fine too. But when you want to change back to QWERTZ you get the following message: Traceback (most recent call last): File "test.py", line 89, in runTouchApp(main_widget)
File "/usr/lib/python2.6/site-packages/pymt/base.py", line 352, in runTouchApp pymt_window.mainloop() File "/usr/lib/python2.6/site-packages/pymt/ui/window/win_pygame.py", line 124, in mainloop evloop.idle() File "/usr/lib/python2.6/site-packages/pymt/base.py", line 196, in idle self.dispatch_input() File "/usr/lib/python2.6/site-packages/pymt/base.py", line 181, in dispatch_input self.post_dispatch_input(type=type, touch=touch) File "/usr/lib/python2.6/site-packages/pymt/base.py", line 151, in post_dispatch_input wid.dispatch_event('on_touch_up', touch) File "/usr/lib/python2.6/site-packages/pymt/event.py", line 349, in dispatch_event event_type, args, getattr(self, event_type)) File "/usr/lib/python2.6/site-packages/pymt/event.py", line 344, in dispatch_event if func(*args): File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/composed/kineticlist.py", line 425, in on_touch_up child.dispatch_event('on_touch_down', touch) File "/usr/lib/python2.6/site-packages/pymt/event.py", line 349, in dispatch_event event_type, args, getattr(self, event_type)) File "/usr/lib/python2.6/site-packages/pymt/event.py", line 344, in dispatch_event if func(*args): File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/button.py", line 153, in on_touch_down self.dispatch_event('on_press', touch) File "/usr/lib/python2.6/site-packages/pymt/event.py", line 337, in dispatch_event self._raise_dispatch_exception(event_type, args, handler) File "/usr/lib/python2.6/site-packages/pymt/event.py", line 334, in dispatch_event if handler(args): File "/usr/lib/python2.6/site-packages/pymt/utils.py", line 32, in call_fn return fn((cargs + fargs), **d) File "/usr/lib/python2.6/site-packages/pymt/ui/widgets/composed/vkeyboard.py", line 432, in on_layout_change self.layout = layout() TypeError: 'KeyboardLayoutQWERTZ' object is not callable

Comment #5

Posted on Jul 4, 2010 by Quick Bird

OK, there is no bug. :-) You're using the API incorrectly. a) add_custom_layout expects a class object, not an object of that class. I.e., don't call add_custom_layout(KeyboardLayoutQWERTZ()), but add_custom_layout(KeyboardLayoutQWERTZ). Then you can just create a MTVKeyboard (even without the layout= parameter) and choose the qwertz layout from the list when you click the button on the bottom left.

b) If you want to give the keyboard the right layout from the start, don't pass an ID but the actual keyboardlayout object. I.e.: k = MTVKeyboard(layout=KeyboardLayoutQWERTZ()) instead of: k = MTVKeyboard(layout='qwertz').

That both works for me. (You are missing a SIZE attribute in your layout. I think you can just copy that one line from the QWERTY layout.)

That should help. I'm marking this issue as invalid since I don't think it's a bug. If you disagree, feel free to post again. Thanks for taking the time to report this issue, nevertheless!

Comment #6

Posted on Jul 4, 2010 by Grumpy Monkey

OK, I became a little bit confused because of the config file were it says layout = qwerty. Thank you for these informations and sorry that I waste your time.

(You are missing a SIZE attribute in your layout. I think you can just copy that one line from the QWERTY layout.) There is no SIZE attribute in the QWERTY layout - I think that's because I don't use the git version.

Status: Invalid

Labels:
Type-Defect Priority-Medium