4 from __future__ import division
10 QtGui = qt_compat.import_module("QtGui")
15 class PieKeyboard(object):
27 MAX_ANGULAR_SLICES = 8
41 SLICE_DIRECTION_NAMES = [
54 self._layout = QtGui.QGridLayout()
55 self._widget = QtGui.QWidget()
56 self._widget.setLayout(self._layout)
64 def add_pie(self, row, column, pieButton):
65 assert len(pieButton) == 8
66 self._layout.addWidget(pieButton, row, column)
67 self.__cells[(row, column)] = pieButton
69 def get_pie(self, row, column):
70 return self.__cells[(row, column)]
73 class KeyboardModifier(object):
75 def __init__(self, name):
82 return self.lock or self.once
84 def on_toggle_lock(self, *args, **kwds):
85 self.lock = not self.lock
87 def on_toggle_once(self, *args, **kwds):
88 self.once = not self.once
94 def parse_keyboard_data(text):
98 def _enumerate_pie_slices(pieData, iconPaths):
99 for direction, directionName in zip(
100 PieKeyboard.SLICE_DIRECTIONS, PieKeyboard.SLICE_DIRECTION_NAMES
102 if directionName in pieData:
103 sliceData = pieData[directionName]
105 action = QtGui.QAction(None)
107 action.setText(sliceData["text"])
111 relativeIconPath = sliceData["path"]
115 for iconPath in iconPaths:
116 absIconPath = os.path.join(iconPath, relativeIconPath)
117 if os.path.exists(absIconPath):
118 action.setIcon(QtGui.QIcon(absIconPath))
120 pieItem = qtpie.QActionPieItem(action)
121 actionToken = sliceData["action"]
123 pieItem = qtpie.PieFiling.NULL_CENTER
125 yield direction, pieItem, actionToken
128 def load_keyboard(keyboardName, dataTree, keyboard, keyboardHandler, iconPaths):
129 for (row, column), pieData in dataTree.iteritems():
130 pieItems = list(_enumerate_pie_slices(pieData, iconPaths))
131 assert pieItems[0][0] == PieKeyboard.SLICE_CENTER, pieItems[0]
132 _, center, centerAction = pieItems.pop(0)
134 pieButton = qtpie.QPieButton(center)
135 pieButton.set_center(center)
136 keyboardHandler.map_slice_action(center, centerAction)
137 for direction, pieItem, action in pieItems:
138 pieButton.insertItem(pieItem)
139 keyboardHandler.map_slice_action(pieItem, action)
140 keyboard.add_pie(row, column, pieButton)
143 class KeyboardHandler(object):
145 def __init__(self, keyhandler):
146 self.__keyhandler = keyhandler
147 self.__commandHandlers = {}
148 self.__modifiers = {}
149 self.__sliceActions = {}
151 self.register_modifier("Shift")
152 self.register_modifier("Super")
153 self.register_modifier("Control")
154 self.register_modifier("Alt")
156 def register_command_handler(self, command, handler):
157 # @todo Look into hooking these up directly to the pie actions
158 self.__commandHandlers["[%s]" % command] = handler
160 def unregister_command_handler(self, command):
161 # @todo Look into hooking these up directly to the pie actions
162 del self.__commandHandlers["[%s]" % command]
164 def register_modifier(self, modifierName):
165 mod = KeyboardModifier(modifierName)
166 self.register_command_handler(modifierName, mod.on_toggle_lock)
167 self.__modifiers["<%s>" % modifierName] = mod
169 def unregister_modifier(self, modifierName):
170 self.unregister_command_handler(modifierName)
171 del self.__modifiers["<%s>" % modifierName]
173 def map_slice_action(self, slice, action):
174 callback = lambda direction: self(direction, action)
175 slice.action().triggered.connect(callback)
176 self.__sliceActions[slice] = (action, callback)
178 def __call__(self, direction, action):
181 for mod in self.__modifiers.itervalues()
185 needResetOnce = False
186 if action.startswith("[") and action.endswith("]"):
187 commandName = action[1:-1]
188 if action in self.__commandHandlers:
189 self.__commandHandlers[action](commandName, activeModifiers)
192 warnings.warn("Unknown command: [%s]" % commandName)
193 elif action.startswith("<") and action.endswith(">"):
194 modName = action[1:-1]
195 for mod in self.__modifiers.itervalues():
196 if mod.name == modName:
200 warnings.warn("Unknown modifier: <%s>" % modName)
202 self.__keyhandler(action, activeModifiers)
206 for mod in self.__modifiers.itervalues():