Package Gnumed :: Package timelinelib :: Package config :: Module shortcut
[frames] | no frames]

Source Code for Module Gnumed.timelinelib.config.shortcut

  1  # Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018  Rickard Lindberg, Roger Lindberg 
  2  # 
  3  # This file is part of Timeline. 
  4  # 
  5  # Timeline is free software: you can redistribute it and/or modify 
  6  # it under the terms of the GNU General Public License as published by 
  7  # the Free Software Foundation, either version 3 of the License, or 
  8  # (at your option) any later version. 
  9  # 
 10  # Timeline is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 13  # GNU General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU General Public License 
 16  # along with Timeline.  If not, see <http://www.gnu.org/licenses/>. 
 17   
 18   
 19  """ 
 20  Naming and other conventions: 
 21  All data needed for configuration of shortcuts are collected in metadata 
 22  objects wich are of type Metadata. 
 23  The text in a menu item to the right of the \t character is called shortcut. 
 24  Examples of shortcuts: Ctrl+N, PgUp, Shift+Ctrl+X 
 25  The shortcut, if it exists, consists of an optional modifier and a shortcut 
 26  key. So the format of a shortcut is: [modifier +] shortcut_key. 
 27  The text in a menu item describing the action is called function. 
 28  wxid is the ID associated with the menu item. 
 29  cfgid is the ID used in the configuration file associated with a shortcut. 
 30  """ 
 31   
 32   
 33  import timelinelib.wxgui.frames.mainframe.guicreator as mf 
 34   
 35   
36 -class Metadata(object):
37 - def __init__(self, wxid, cfgid, function, modifier, key):
38 self.wxid = wxid 39 self.cfgid = cfgid 40 self.function = function 41 self.modifier = modifier 42 self.key = key
43 44 45 CTRL_MODIFIER = "Ctrl" 46 ALT_MODIFIER = "Alt" 47 NO_MODIFIER = "" 48 LABEL = "%s->%%s" 49 LABEL_FILE = LABEL % _("File") 50 LABEL_EDIT = LABEL % _("Edit") 51 LABEL_VIEW = LABEL % _("View") 52 LABEL_TIMELINE = LABEL % _("Timeline") 53 LABEL_NAVIGATE = LABEL % _("Navigate") 54 LABEL_HELP = LABEL % _("Help") 55 NAVLABEL = "%s(%s)->%%s" 56 LABEL_NAVIGATE_TIME = NAVLABEL % (_("Navigate"), "tm") 57 LABEL_NAVIGATE_NUM = NAVLABEL % (_("Navigate"), "num") 58 METADATA = [ # File 59 Metadata(mf.ID_NEW, "shortcut_file_new", LABEL_FILE % _("New..."), CTRL_MODIFIER, "N"), 60 Metadata(mf.ID_SAVEAS, "shortcut_save_as", LABEL_FILE % _("Save As..."), NO_MODIFIER, ""), 61 Metadata(mf.ID_IMPORT, "shortcut_import", LABEL_FILE % _("Import..."), NO_MODIFIER, ""), 62 Metadata(mf.ID_EXPORT, "shortcut_export", LABEL_FILE % _("Export Current view to Image..."), NO_MODIFIER, ""), 63 Metadata(mf.ID_EXPORT_ALL, "shortcut_export_all", LABEL_FILE % _("Export Whole Timeline to Images..."), NO_MODIFIER, ""), 64 Metadata(mf.ID_EXPORT_SVG, "shortcut_export_svg", LABEL_FILE % _("Export to SVG..."), NO_MODIFIER, ""), 65 Metadata(mf.ID_EXIT, "shortcut_exit", LABEL_FILE % _("Exit"), NO_MODIFIER, ""), 66 # Edit 67 Metadata(mf.ID_FIND, "shortcut_find", LABEL_EDIT % _("Find"), CTRL_MODIFIER, "F"), 68 Metadata(mf.ID_PREFERENCES, "shortcut_preferences", LABEL_EDIT % _("Preferences"), NO_MODIFIER, ""), 69 Metadata(mf.ID_SELECT_ALL, "shortcut_selectall", LABEL_EDIT % _("Select All Events"), NO_MODIFIER, ""), 70 Metadata(mf.ID_EDIT_SHORTCUTS, "shortcut_shortcuts", LABEL_EDIT % _("Shortcuts"), NO_MODIFIER, ""), 71 # View 72 Metadata(mf.ID_SIDEBAR, "shortcut_sidebar", LABEL_VIEW % _("Sidebar"), CTRL_MODIFIER, "I"), 73 Metadata(mf.ID_LEGEND, "shortcut_legend", LABEL_VIEW % _("Legend"), NO_MODIFIER, ""), 74 Metadata(mf.ID_BALLOONS, "shortcut_ballons", LABEL_VIEW % _("Ballons on hover"), NO_MODIFIER, ""), 75 Metadata(mf.ID_ZOOMIN, "shortcut_zoomin", LABEL_VIEW % _("Zoom In"), CTRL_MODIFIER, "+"), 76 Metadata(mf.ID_ZOOMOUT, "shortcut_zoomout", LABEL_VIEW % _("Zoom Out"), CTRL_MODIFIER, "-"), 77 Metadata(mf.ID_VERT_ZOOMIN, "shortcut_vertical_zoomin", LABEL_VIEW % _("Vertical Zoom In"), ALT_MODIFIER, "+"), 78 Metadata(mf.ID_VERT_ZOOMOUT, "shortcut_vertical_zoomout", LABEL_VIEW % _("Vertical Zoom Out"), ALT_MODIFIER, "-"), 79 Metadata(mf.ID_PRESENTATION, "shortcut_slideshow", LABEL_VIEW % _("Start slide show"), ALT_MODIFIER, "-"), 80 # Timeline 81 Metadata(mf.ID_CREATE_EVENT, "shortcut_create_event", LABEL_TIMELINE % _("Create Event"), NO_MODIFIER, ""), 82 Metadata(mf.ID_EDIT_EVENT, "shortcut_edit_event", LABEL_TIMELINE % _("Edit Selected Event"), NO_MODIFIER, ""), 83 Metadata(mf.ID_DUPLICATE_EVENT, "shortcut_duplicate_event", LABEL_TIMELINE % _("Duplicate Selected Event"), NO_MODIFIER, ""), 84 Metadata(mf.ID_SET_CATEGORY_ON_SELECTED, "shortcut_set_category_on_selected", 85 LABEL_TIMELINE % _("Set Category on Selected Events"), NO_MODIFIER, ""), 86 Metadata(mf.ID_MEASURE_DISTANCE, "shortcut_measure_distance", LABEL_TIMELINE % _("Measure Distance between two Events"), NO_MODIFIER, ""), 87 Metadata(mf.ID_SET_CATEGORY_ON_WITHOUT, "shortcut_set_category_on_without", 88 LABEL_TIMELINE % _("Set Category on events without category"), NO_MODIFIER, ""), 89 Metadata(mf.ID_SET_READONLY, "shortcut_set_readonly", LABEL_TIMELINE % _("Read Only"), NO_MODIFIER, ""), 90 Metadata(mf.ID_UNDO, "shortcut_undo", LABEL_TIMELINE % _("Undo"), CTRL_MODIFIER, "Z"), 91 Metadata(mf.ID_REDO, "shortcut_redo", LABEL_TIMELINE % _("Redo"), ALT_MODIFIER, "Z"), 92 # Help 93 Metadata(mf.ID_HELP, "shortcut_help_content", LABEL_HELP % _("Contents"), NO_MODIFIER, "F1"), 94 Metadata(mf.ID_TUTORIAL, "shortcut_tutorial", LABEL_HELP % _("Getting started tutorial"), NO_MODIFIER, ""), 95 Metadata(mf.ID_FEEDBACK, "shortcut_feedback", LABEL_HELP % _("Give Feedback"), NO_MODIFIER, ""), 96 Metadata(mf.ID_CONTACT, "shortcut_contact", LABEL_HELP % _("Contact"), NO_MODIFIER, ""), 97 Metadata(mf.ID_ABOUT, "shortcut_about", LABEL_HELP % _("About"), NO_MODIFIER, ""), 98 # Navigate 99 Metadata(mf.ID_FIND_FIRST, "shortcut_find_first_event", LABEL_NAVIGATE % _("Find First Event"), NO_MODIFIER, ""), 100 Metadata(mf.ID_FIND_LAST, "shortcut_find_last_event", LABEL_NAVIGATE % _("Find Last Event"), NO_MODIFIER, ""), 101 Metadata(mf.ID_FIT_ALL, "shortcut_find_all_events", LABEL_NAVIGATE % _("Find All Events"), NO_MODIFIER, ""), 102 ] 103 FUNCTION_KEYS = ["PgDn", "PgUp", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"] 104 SHORTCUT_KEYS = ["", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", 105 "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", 106 "1", "2", "3", "4", "5", "6", "7", "8", "9", 107 "+", "-", 108 ] + FUNCTION_KEYS 109 NON_EMPTY_MODIFIERS = ["Ctrl", "Alt", "Shift+Ctrl", "Shift+Alt", "Alt+Ctrl", "Shift+Alt+Ctrl"] 110 MODIFIERS = ["", ] + NON_EMPTY_MODIFIERS 111 112
113 -class ShortcutController(object):
114
115 - def __init__(self, shortcut_config, wxItems):
116 self.shortcut_config = shortcut_config 117 self.wxItems = wxItems
118
119 - def load_config_settings(self):
120 for metadata in METADATA: 121 self._load_config_setting(metadata)
122
123 - def get_functions(self):
124 return [metadata.function for metadata in METADATA]
125
126 - def get_modifiers(self):
127 return MODIFIERS
128
129 - def get_shortcuts(self):
130 return SHORTCUT_KEYS
131
132 - def get_function(self, shortcut):
133 for metadata in METADATA: 134 if self._shortcut_from_metadata(metadata) == shortcut: 135 return metadata.function
136
137 - def get_modifier_and_key(self, function):
138 for metadata in METADATA: 139 if metadata.function == function: 140 return metadata.modifier, metadata.key
141
142 - def is_valid(self, modifier, shortcut_key):
143 if modifier == "": 144 return shortcut_key in [""] + FUNCTION_KEYS 145 else: 146 return modifier in MODIFIERS and shortcut_key in SHORTCUT_KEYS[1:]
147
148 - def exists(self, shortcut):
149 return shortcut in [self._shortcut_from_metadata(metadata) for metadata in METADATA 150 if self._shortcut_from_metadata(metadata) != ""]
151
152 - def wxid_exists(self, wxid):
153 return wxid in [shortcut.wxid for shortcut in METADATA]
154
155 - def is_function_key(self, shortcut):
156 return shortcut in FUNCTION_KEYS
157
158 - def add_navigation_functions(self):
159 self._add_time_navigation_functions() 160 self._add_numeric_navigation_functions()
161
162 - def edit(self, function, new_shortcut):
163 for metadata in METADATA: 164 if metadata.function == function: 165 try: 166 self._edit(metadata.wxid, new_shortcut, self.wxItems[metadata.wxid]) 167 except KeyError: 168 pass
169 170 # 171 # Internals 172 #
174 self._add_navigation_functions(0, LABEL_NAVIGATE_TIME)
175
177 self._add_navigation_functions(100, LABEL_NAVIGATE_NUM)
178
179 - def _add_navigation_functions(self, id_offset, function_format):
180 try: 181 pos = id_offset 182 while True: 183 wxid = mf.ID_NAVIGATE + pos 184 if not self.wxid_exists(wxid): 185 self._add_navigation_function(wxid, function_format) 186 else: 187 self._set_menuitem_shortcut(wxid) 188 pos += 1 189 except KeyError: 190 # We will end up here when there are no more navigation functions 191 pass
192
193 - def _add_navigation_function(self, wxid, function_format):
194 function = self._get_function_from_menuitem(wxid) 195 modifier, shortcut_key = self._get_modifier_and_key_from_menuitem(wxid) 196 metadata = Metadata(wxid, "shortcut_navigate_%s" % str(wxid), function_format % function, modifier, shortcut_key) 197 METADATA.append(metadata) 198 self._load_config_setting(metadata)
199
200 - def _get_function_from_menuitem(self, wxid):
201 menu_item = self.wxItems[wxid] 202 label = menu_item.GetItemLabel() 203 function = label.split("\t")[0] 204 function = function.replace("&", "") 205 return function
206
208 menu_item = self.wxItems[wxid] 209 label = menu_item.GetItemLabel() 210 try: 211 shortcut = label.split("\t")[1] 212 try: 213 modifier, shortcut_key = shortcut.split("+") 214 except: 215 modifier, shortcut_key = ("", shortcut) 216 except: 217 modifier, shortcut_key = ("", "") 218 if shortcut_key not in SHORTCUT_KEYS: 219 modifier, shortcut_key = ("", "") 220 return modifier, shortcut_key
221
222 - def _load_config_setting(self, metadata):
223 shortcut = self._shortcut_from_metadata(metadata) 224 shortcut = self.shortcut_config.get_shortcut_key(metadata.cfgid, shortcut) 225 self.edit(metadata.function, shortcut)
226
227 - def _edit(self, wxid, new_shortcut, menu_item):
228 if new_shortcut == "": 229 new_shortcut = "+" 230 if self._valid(new_shortcut): 231 for metadata in METADATA: 232 if metadata.wxid == wxid: 233 self._edit_shortcut(metadata, new_shortcut, menu_item) 234 break
235
236 - def _valid(self, shortcut):
237 if shortcut == "+": 238 return True 239 return not self.exists(shortcut)
240
241 - def _edit_shortcut(self, metadata, new_shortcut, menu_item):
242 try: 243 metadata.modifier, metadata.key = new_shortcut.rsplit("+", 1) 244 except: 245 metadata.modifier, metadata.key = ("", new_shortcut) 246 self.shortcut_config.set_shortcut_key(metadata.cfgid, new_shortcut) 247 self._set_menuitem_label(menu_item, new_shortcut)
248
249 - def _set_menuitem_label(self, menu_item, new_shortcut):
250 label = menu_item.GetItemLabel() 251 prefix = label.split("\t")[0] 252 if new_shortcut in ("", "+"): 253 new_label = prefix 254 else: 255 new_label = "%s\t%s" % (prefix, new_shortcut) 256 menu_item.SetItemLabel(new_label)
257
258 - def _shortcut_from_metadata(self, metadata):
259 if metadata.modifier != "": 260 return "%s+%s" % (metadata.modifier, metadata.key) 261 else: 262 return metadata.key
263
264 - def _set_menuitem_shortcut(self, wxid):
265 menu_item = self.wxItems[wxid] 266 for metadata in METADATA: 267 if metadata.wxid == wxid: 268 shortcut_key = self._shortcut_from_metadata(metadata) 269 self._set_menuitem_label(menu_item, shortcut_key) 270 break
271