4 from __future__ import division
9 from PyQt4 import QtGui
10 from PyQt4 import QtCore
15 class PieKeyboard(object):
27 MAX_ANGULAR_SLICES = 8
41 SLICE_DIRECTION_NAMES = [
53 def __init__(self, rows, columns):
54 self._layout = QtGui.QGridLayout()
62 def add_pie(self, row, column, pieButton):
63 assert len(pieButton) == 8
64 self._layout.addWidget(pieButton, row, column)
65 self.__cells[(row, column)] = pieButton
67 def get_pie(self, row, column):
68 return self.__cells[(row, column)]
71 class KeyboardModifier(object):
73 def __init__(self, name):
80 return self.lock or self.once
82 def on_toggle_lock(self, *args, **kwds):
83 self.lock = not self.lock
85 def on_toggle_once(self, *args, **kwds):
86 self.once = not self.once
92 def parse_keyboard_data(text):
96 def _enumerate_pie_slices(pieData, iconPaths):
97 for direction, directionName in zip(
98 PieKeyboard.SLICE_DIRECTIONS, PieKeyboard.SLICE_DIRECTION_NAMES
100 if directionName in pieData:
101 sliceData = pieData[directionName]
103 action = QtGui.QAction(None)
105 action.setText(sliceData["text"])
109 relativeIconPath = sliceData["path"]
113 for iconPath in iconPaths:
114 absIconPath = os.path.join(iconPath, relativeIconPath)
115 if os.path.exists(absIconPath):
116 action.setIcon(QtGui.QIcon(absIconPath))
118 pieItem = qtpie.QActionPieItem(action)
119 actionToken = sliceData["action"]
121 pieItem = qtpie.PieFiling.NULL_CENTER
123 yield direction, pieItem, actionToken
126 def load_keyboard(keyboardName, dataTree, keyboard, keyboardHandler, iconPaths):
127 for (row, column), pieData in dataTree.iteritems():
128 pieItems = list(_enumerate_pie_slices(pieData, iconPaths))
129 assert pieItems[0][0] == PieKeyboard.SLICE_CENTER, pieItems[0]
130 _, center, centerAction = pieItems.pop(0)
132 pieButton = qtpie.QPieButton(center)
133 pieButton.set_center(center)
134 keyboardHandler.map_slice_action(center, centerAction)
135 for direction, pieItem, action in pieItems:
136 pieButton.insertItem(pieItem)
137 keyboardHandler.map_slice_action(pieItem, action)
138 keyboard.add_pie(row, column, pieButton)
141 class KeyboardHandler(object):
143 def __init__(self, keyhandler):
144 self.__keyhandler = keyhandler
145 self.__commandHandlers = {}
146 self.__modifiers = {}
147 self.__sliceActions = {}
149 self.register_modifier("Shift")
150 self.register_modifier("Super")
151 self.register_modifier("Control")
152 self.register_modifier("Alt")
154 def register_command_handler(self, command, handler):
155 # @todo Look into hooking these up directly to the pie actions
156 self.__commandHandlers["[%s]" % command] = handler
158 def unregister_command_handler(self, command):
159 # @todo Look into hooking these up directly to the pie actions
160 del self.__commandHandlers["[%s]" % command]
162 def register_modifier(self, modifierName):
163 mod = KeyboardModifier(modifierName)
164 self.register_command_handler(modifierName, mod.on_toggle_lock)
165 self.__modifiers["<%s>" % modifierName] = mod
167 def unregister_modifier(self, modifierName):
168 self.unregister_command_handler(modifierName)
169 del self.__modifiers["<%s>" % modifierName]
171 def map_slice_action(self, slice, action):
172 callback = lambda direction: self(direction, action)
173 slice.action().triggered.connect(callback)
174 self.__sliceActions[slice] = (action, callback)
176 def __call__(self, direction, action):
179 for mod in self.__modifiers.itervalues()
183 needResetOnce = False
184 if action.startswith("[") and action.endswith("]"):
185 commandName = action[1:-1]
186 if action in self.__commandHandlers:
187 self.__commandHandlers[action](commandName, activeModifiers)
190 warnings.warn("Unknown command: [%s]" % commandName)
191 elif action.startswith("<") and action.endswith(">"):
192 modName = action[1:-1]
193 for mod in self.__modifiers.itervalues():
194 if mod.name == modName:
198 warnings.warn("Unknown modifier: <%s>" % modName)
200 self.__keyhandler(action, activeModifiers)
204 for mod in self.__modifiers.itervalues():