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 = [
54 self._layout = QtGui.QGridLayout()
63 for cell in self.__cells.itervalues():
67 for cell in self.__cells.itervalues():
70 def add_pie(self, row, column, pieButton):
71 assert len(pieButton) == 8
72 self._layout.addWidget(pieButton, row, column)
73 self.__cells[(row, column)] = pieButton
75 def get_pie(self, row, column):
76 return self.__cells[(row, column)]
79 class KeyboardModifier(object):
81 def __init__(self, name):
88 return self.lock or self.once
90 def on_toggle_lock(self, *args, **kwds):
91 self.lock = not self.lock
93 def on_toggle_once(self, *args, **kwds):
94 self.once = not self.once
100 def parse_keyboard_data(text):
104 def _enumerate_pie_slices(pieData, iconPaths):
105 for direction, directionName in zip(
106 PieKeyboard.SLICE_DIRECTIONS, PieKeyboard.SLICE_DIRECTION_NAMES
108 if directionName in pieData:
109 sliceData = pieData[directionName]
111 action = QtGui.QAction(None)
113 action.setText(sliceData["text"])
117 relativeIconPath = sliceData["path"]
121 for iconPath in iconPaths:
122 absIconPath = os.path.join(iconPath, relativeIconPath)
123 if os.path.exists(absIconPath):
124 action.setIcon(QtGui.QIcon(absIconPath))
126 pieItem = qtpie.QActionPieItem(action)
127 actionToken = sliceData["action"]
129 pieItem = qtpie.PieFiling.NULL_CENTER
131 yield direction, pieItem, actionToken
134 def load_keyboard(keyboardName, dataTree, keyboard, keyboardHandler, iconPaths):
135 for (row, column), pieData in dataTree.iteritems():
136 pieItems = list(_enumerate_pie_slices(pieData, iconPaths))
137 assert pieItems[0][0] == PieKeyboard.SLICE_CENTER, pieItems[0]
138 _, center, centerAction = pieItems.pop(0)
140 pieButton = qtpie.QPieButton(center)
141 pieButton.set_center(center)
142 keyboardHandler.map_slice_action(center, centerAction)
143 for direction, pieItem, action in pieItems:
144 pieButton.insertItem(pieItem)
145 keyboardHandler.map_slice_action(pieItem, action)
146 keyboard.add_pie(row, column, pieButton)
149 class KeyboardHandler(object):
151 def __init__(self, keyhandler):
152 self.__keyhandler = keyhandler
153 self.__commandHandlers = {}
154 self.__modifiers = {}
155 self.__sliceActions = {}
157 self.register_modifier("Shift")
158 self.register_modifier("Super")
159 self.register_modifier("Control")
160 self.register_modifier("Alt")
162 def register_command_handler(self, command, handler):
163 # @todo Look into hooking these up directly to the pie actions
164 self.__commandHandlers["[%s]" % command] = handler
166 def unregister_command_handler(self, command):
167 # @todo Look into hooking these up directly to the pie actions
168 del self.__commandHandlers["[%s]" % command]
170 def register_modifier(self, modifierName):
171 mod = KeyboardModifier(modifierName)
172 self.register_command_handler(modifierName, mod.on_toggle_lock)
173 self.__modifiers["<%s>" % modifierName] = mod
175 def unregister_modifier(self, modifierName):
176 self.unregister_command_handler(modifierName)
177 del self.__modifiers["<%s>" % modifierName]
179 def map_slice_action(self, slice, action):
180 callback = lambda direction: self(direction, action)
181 slice.action().triggered.connect(callback)
182 self.__sliceActions[slice] = (action, callback)
184 def __call__(self, direction, action):
187 for mod in self.__modifiers.itervalues()
191 needResetOnce = False
192 if action.startswith("[") and action.endswith("]"):
193 commandName = action[1:-1]
194 if action in self.__commandHandlers:
195 self.__commandHandlers[action](commandName, activeModifiers)
198 warnings.warn("Unknown command: [%s]" % commandName)
199 elif action.startswith("<") and action.endswith(">"):
200 modName = action[1:-1]
201 for mod in self.__modifiers.itervalues():
202 if mod.name == modName:
206 warnings.warn("Unknown modifier: <%s>" % modName)
208 self.__keyhandler(action, activeModifiers)
212 for mod in self.__modifiers.itervalues():