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_EDIT_CATEGORIES, "shortcut_edit_categories", LABEL_TIMELINE % _("Edit Categories"), NO_MODIFIER, ""),
     90                Metadata(mf.ID_SET_READONLY, "shortcut_set_readonly", LABEL_TIMELINE % _("Read Only"), NO_MODIFIER, ""),
     91                Metadata(mf.ID_UNDO, "shortcut_undo", LABEL_TIMELINE % _("Undo"), CTRL_MODIFIER, "Z"),
     92                Metadata(mf.ID_REDO, "shortcut_redo", LABEL_TIMELINE % _("Redo"), ALT_MODIFIER, "Z"),
     93                # Help
     94                Metadata(mf.ID_HELP, "shortcut_help_content", LABEL_HELP % _("Contents"), NO_MODIFIER, "F1"),
     95                Metadata(mf.ID_TUTORIAL, "shortcut_tutorial", LABEL_HELP % _("Getting started tutorial"), NO_MODIFIER, ""),
     96                Metadata(mf.ID_FEEDBACK, "shortcut_feedback", LABEL_HELP % _("Give Feedback"), NO_MODIFIER, ""),
     97                Metadata(mf.ID_CONTACT, "shortcut_contact", LABEL_HELP % _("Contact"), NO_MODIFIER, ""),
     98                Metadata(mf.ID_ABOUT, "shortcut_about", LABEL_HELP % _("About"), NO_MODIFIER, ""),
     99                # Navigate
    100                Metadata(mf.ID_FIND_FIRST, "shortcut_find_first_event", LABEL_NAVIGATE % _("Find First Event"), NO_MODIFIER, ""),
    101                Metadata(mf.ID_FIND_LAST, "shortcut_find_last_event", LABEL_NAVIGATE % _("Find Last Event"), NO_MODIFIER, ""),
    102                Metadata(mf.ID_FIT_ALL, "shortcut_find_all_events", LABEL_NAVIGATE % _("Find All Events"), NO_MODIFIER, ""),
    103      ]
    104  FUNCTION_KEYS = ["PgDn", "PgUp", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"]
    105  SHORTCUT_KEYS = ["", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
    106                   "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
    107                   "1", "2", "3", "4", "5", "6", "7", "8", "9",
    108                   "+", "-",
    109                   ] + FUNCTION_KEYS
    110  NON_EMPTY_MODIFIERS = ["Ctrl", "Alt", "Shift+Ctrl", "Shift+Alt", "Alt+Ctrl", "Shift+Alt+Ctrl"]
    111  MODIFIERS = ["", ] + NON_EMPTY_MODIFIERS
    112
    113
    114 -class ShortcutController(object):
    115
    116 -    def __init__(self, shortcut_config, wxItems):
    117          self.shortcut_config = shortcut_config
    118          self.wxItems = wxItems
    119
    120 -    def load_config_settings(self):
    121          for metadata in METADATA:
    122              self._load_config_setting(metadata)
    123
    124 -    def get_functions(self):
    125          return [metadata.function for metadata in METADATA]
    126
    127 -    def get_modifiers(self):
    128          return MODIFIERS
    129
    130 -    def get_shortcuts(self):
    131          return SHORTCUT_KEYS
    132
    133 -    def get_function(self, shortcut):
    134          for metadata in METADATA:
    135              if self._shortcut_from_metadata(metadata) == shortcut:
    136                  return metadata.function
    137
    138 -    def get_modifier_and_key(self, function):
    139          for metadata in METADATA:
    140              if metadata.function == function:
    141                  return metadata.modifier, metadata.key
    142
    143 -    def is_valid(self, modifier, shortcut_key):
    144          if modifier == "":
    145              return shortcut_key in [""] + FUNCTION_KEYS
    146          else:
    147              return modifier in MODIFIERS and shortcut_key in SHORTCUT_KEYS[1:]
    148
    149 -    def exists(self, shortcut):
    150          return shortcut in [self._shortcut_from_metadata(metadata) for metadata in METADATA
    151                              if self._shortcut_from_metadata(metadata) != ""]
    152
    153 -    def wxid_exists(self, wxid):
    154          return wxid in [shortcut.wxid for shortcut in METADATA]
    155
    156 -    def is_function_key(self, shortcut):
    157          return shortcut in FUNCTION_KEYS
    158
    162
    163 -    def edit(self, function, new_shortcut):
    164          for metadata in METADATA:
    165              if metadata.function == function:
    166                  try:
    167                      self._edit(metadata.wxid, new_shortcut, self.wxItems[metadata.wxid])
    168                  except KeyError:
    169                      pass
    170
    171      #
    172      # Internals
    173      #
    176
    179
    193
    200
    201 -    def _get_function_from_menuitem(self, wxid):
    202          menu_item = self.wxItems[wxid]
    203          label = menu_item.GetItemLabel()
    204          function = label.split("\t")[0]
    205          function = function.replace("&", "")
    206          return function
    207
    208 -    def _get_modifier_and_key_from_menuitem(self, wxid):
    209          menu_item = self.wxItems[wxid]
    210          label = menu_item.GetItemLabel()
    211          try:
    212              shortcut = label.split("\t")[1]
    213              try:
    214                  modifier, shortcut_key = shortcut.split("+")
    215              except:
    216                  modifier, shortcut_key = ("", shortcut)
    217          except:
    218              modifier, shortcut_key = ("", "")
    219          if shortcut_key not in SHORTCUT_KEYS:
    220              modifier, shortcut_key = ("", "")
    221          return modifier, shortcut_key
    222
    223 -    def _load_config_setting(self, metadata):
    224          shortcut = self._shortcut_from_metadata(metadata)
    225          shortcut = self.shortcut_config.get_shortcut_key(metadata.cfgid, shortcut)
    226          self.edit(metadata.function, shortcut)
    227
    228 -    def _edit(self, wxid, new_shortcut, menu_item):
    229          if new_shortcut == "":
    230              new_shortcut = "+"
    231          if self._valid(new_shortcut):
    232              for metadata in METADATA:
    233                  if metadata.wxid == wxid:
    234                      self._edit_shortcut(metadata, new_shortcut, menu_item)
    235                      break
    236
    237 -    def _valid(self, shortcut):
    238          if shortcut == "+":
    239              return True
    240          return not self.exists(shortcut)
    241
    242 -    def _edit_shortcut(self, metadata, new_shortcut, menu_item):
    243          try:
    244              metadata.modifier, metadata.key = new_shortcut.rsplit("+", 1)
    245          except:
    246              metadata.modifier, metadata.key = ("", new_shortcut)
    247          self.shortcut_config.set_shortcut_key(metadata.cfgid, new_shortcut)
    248          self._set_menuitem_label(menu_item, new_shortcut)
    249
    250 -    def _set_menuitem_label(self, menu_item, new_shortcut):
    251          label = menu_item.GetItemLabel()
    252          prefix = label.split("\t")[0]
    253          if new_shortcut in ("", "+"):
    254              new_label = prefix
    255          else:
    256              new_label = "%s\t%s" % (prefix, new_shortcut)
    257          menu_item.SetItemLabel(new_label)
    258
    259 -    def _shortcut_from_metadata(self, metadata):
    260          if metadata.modifier != "":
    261              return "%s+%s" % (metadata.modifier, metadata.key)
    262          else:
    263              return metadata.key
    264
    265 -    def _set_menuitem_shortcut(self, wxid):
    266          menu_item = self.wxItems[wxid]
    267          for metadata in METADATA:
    268              if metadata.wxid == wxid:
    269                  shortcut_key = self._shortcut_from_metadata(metadata)
    270                  self._set_menuitem_label(menu_item, shortcut_key)
    271                  break
    272