4 from __future__ import division
9 from PyQt4 import QtGui
14 class PieKeyboard(object):
26 MAX_ANGULAR_SLICES = 8
40 SLICE_DIRECTION_NAMES = [
52 def __init__(self, rows, columns):
53 self._layout = QtGui.QGridLayout()
54 self._widget = QtGui.QWidget()
55 self._widget.setLayout(self._layout)
63 def add_pie(self, row, column, pieButton):
64 assert len(pieButton) == 8
65 self._layout.addWidget(pieButton, row, column)
66 self.__cells[(row, column)] = pieButton
68 def get_pie(self, row, column):
69 return self.__cells[(row, column)]
72 class KeyboardModifier(object):
74 def __init__(self, name):
81 return self.lock or self.once
83 def on_toggle_lock(self, *args, **kwds):
84 self.lock = not self.lock
86 def on_toggle_once(self, *args, **kwds):
87 self.once = not self.once
93 def parse_keyboard_data(text):
97 def _enumerate_pie_slices(pieData, iconPaths):
98 for direction, directionName in zip(
99 PieKeyboard.SLICE_DIRECTIONS, PieKeyboard.SLICE_DIRECTION_NAMES
101 if directionName in pieData:
102 sliceData = pieData[directionName]
104 action = QtGui.QAction(None)
106 action.setText(sliceData["text"])
110 relativeIconPath = sliceData["path"]
114 for iconPath in iconPaths:
115 absIconPath = os.path.join(iconPath, relativeIconPath)
116 if os.path.exists(absIconPath):
117 action.setIcon(QtGui.QIcon(absIconPath))
119 pieItem = qtpie.QActionPieItem(action)
120 actionToken = sliceData["action"]
122 pieItem = qtpie.PieFiling.NULL_CENTER
124 yield direction, pieItem, actionToken
127 def load_keyboard(keyboardName, dataTree, keyboard, keyboardHandler, iconPaths):
128 for (row, column), pieData in dataTree.iteritems():
129 pieItems = list(_enumerate_pie_slices(pieData, iconPaths))
130 assert pieItems[0][0] == PieKeyboard.SLICE_CENTER, pieItems[0]
131 _, center, centerAction = pieItems.pop(0)
133 pieButton = qtpie.QPieButton(center)
134 pieButton.set_center(center)
135 keyboardHandler.map_slice_action(center, centerAction)
136 for direction, pieItem, action in pieItems:
137 pieButton.insertItem(pieItem)
138 keyboardHandler.map_slice_action(pieItem, action)
139 keyboard.add_pie(row, column, pieButton)
142 class KeyboardHandler(object):
144 def __init__(self, keyhandler):
145 self.__keyhandler = keyhandler
146 self.__commandHandlers = {}
147 self.__modifiers = {}
148 self.__sliceActions = {}
150 self.register_modifier("Shift")
151 self.register_modifier("Super")
152 self.register_modifier("Control")
153 self.register_modifier("Alt")
155 def register_command_handler(self, command, handler):
156 # @todo Look into hooking these up directly to the pie actions
157 self.__commandHandlers["[%s]" % command] = handler
159 def unregister_command_handler(self, command):
160 # @todo Look into hooking these up directly to the pie actions
161 del self.__commandHandlers["[%s]" % command]
163 def register_modifier(self, modifierName):
164 mod = KeyboardModifier(modifierName)
165 self.register_command_handler(modifierName, mod.on_toggle_lock)
166 self.__modifiers["<%s>" % modifierName] = mod
168 def unregister_modifier(self, modifierName):
169 self.unregister_command_handler(modifierName)
170 del self.__modifiers["<%s>" % modifierName]
172 def map_slice_action(self, slice, action):
173 callback = lambda direction: self(direction, action)
174 slice.action().triggered.connect(callback)
175 self.__sliceActions[slice] = (action, callback)
177 def __call__(self, direction, action):
180 for mod in self.__modifiers.itervalues()
184 needResetOnce = False
185 if action.startswith("[") and action.endswith("]"):
186 commandName = action[1:-1]
187 if action in self.__commandHandlers:
188 self.__commandHandlers[action](commandName, activeModifiers)
191 warnings.warn("Unknown command: [%s]" % commandName)
192 elif action.startswith("<") and action.endswith(">"):
193 modName = action[1:-1]
194 for mod in self.__modifiers.itervalues():
195 if mod.name == modName:
199 warnings.warn("Unknown modifier: <%s>" % modName)
201 self.__keyhandler(action, activeModifiers)
205 for mod in self.__modifiers.itervalues():