groupedelements.py 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. """
  2. Module to easily group elements of a gui
  3. """
  4. from PyQt4 import QtGui
  5. import warnings
  6. from itertools import chain
  7. class GroupWarning(Warning):
  8. """
  9. General Warning Class for GroupedObjects
  10. """
  11. pass
  12. warnings.simplefilter('always', GroupWarning)
  13. class GroupedObjects:
  14. """
  15. This class enables grouping of objects to easily access them as groups throughout the gui.
  16. """
  17. def __init__(self):
  18. """
  19. Initialise this object
  20. :return:
  21. """
  22. self._objects = {}
  23. self._status = {}
  24. self.warn = False
  25. self.autoremove = False
  26. self.exception_on_deleted = False
  27. self.notify_deletion = False
  28. def setFlags(self, flagDict):
  29. """
  30. Set Flags that define the behaviour of GroupedObjects in various events.
  31. :param flagDict: Dictionary containing the Flags.
  32. Possible Flags are: (They are to be of type bool)
  33. * warn: If an element is deleted and the corresponding entry is encountered by setEnabled, a
  34. Warning is raised if warn is True
  35. * autoremove: If an element is deleted and the corresponding entry is encountered by setEnabled,
  36. the Element will be removed from GroupedObjects if autoremove is True
  37. * exception_on_deleted: If an element is deleted and the corresponding entry is encountered by
  38. setEnabled an Exception will be raised if exception_on_deleted is True
  39. * notify_deletion: If this is set to True a notification will be printed to STDOUT whenever an
  40. autoremove is performed (see above)
  41. :return: -
  42. """
  43. self.warn = flagDict.get('warn', False)
  44. self.autoremove = flagDict.get('autoremove', False)
  45. self.exception_on_deleted = flagDict.get('exception_on_deleted', False)
  46. self.notify_deletion = flagDict.get('notify_deletion', False)
  47. def createEmptyGroup(self, group):
  48. """
  49. Create an empty group
  50. :param group: (str) the name of the group
  51. :return: -
  52. """
  53. if group in self._objects:
  54. raise GroupWarning("Specified Group \""+group+"\" already in list")
  55. else:
  56. self._objects[group] = []
  57. def addItem(self, group, item):
  58. """
  59. Add a item or items to a group and thus register with the GroupedObjects object
  60. :param group: (list or str) List of groups or single group where the item is to be added
  61. :param item: (single item or list) What item/s
  62. :return: -
  63. """
  64. group = group if isinstance(group, list) else [group]
  65. item = item if isinstance(item, list) else [item]
  66. exclude = list(chain(*[self.getElements(i) for i in group]))
  67. for gr in group:
  68. if not (gr in self._status):
  69. self._status[gr] = True
  70. if gr in self._objects and isinstance(self._objects[gr], list):
  71. self._objects[gr].extend(item)
  72. else:
  73. self._objects[gr] = item
  74. if not self._status[gr]: # for the case when the status is set before the object is registered or the object is recreated
  75. self.setEnabled(gr, False, exclude=exclude)
  76. def setChecked(self, group, state):
  77. """
  78. Set the state of all the checkboxes in the group
  79. :param group: What group
  80. :param state: True for checked, False for unchecked
  81. :return: -
  82. """
  83. if group in self._objects:
  84. self._status[group] = state
  85. for obj in self._objects[group]:
  86. if isinstance(obj, QtGui.QCheckBox):
  87. obj.setChecked(state)
  88. else:
  89. warnings.warn("Specified Group \""+group+"\" not in list", GroupWarning, stacklevel=2)
  90. def setEnabled(self, group, state, exclude=None):
  91. """
  92. Set the state of all the items in the group
  93. :param group: What group
  94. :param state: True for enabled, False for disabled
  95. :param exclude: Exclude this item
  96. :return: -
  97. """
  98. to_remove = []
  99. if group in self._objects:
  100. self._status[group] = state
  101. if self._objects[group] == []: # untested if explicit test for empty list is necessary
  102. return
  103. for obj in self._objects[group]:
  104. try:
  105. if exclude and obj in exclude:
  106. continue
  107. if isinstance(obj, QtGui.QAction):
  108. obj.setEnabled(state)
  109. elif isinstance(obj, QtGui.QMenu):
  110. obj.menuAction().setVisible(state)
  111. else:
  112. obj.setEnabled(state)
  113. except RuntimeError as e:
  114. if "deleted" in str(e):
  115. # self.removeItem(group, obj)
  116. if self.autoremove:
  117. to_remove.append([group, obj])
  118. if self.warn:
  119. warnings.warn(str(e), GroupWarning, stacklevel=3)
  120. if self.exception_on_deleted:
  121. raise e
  122. else:
  123. raise e
  124. if to_remove and self.autoremove:
  125. for rm in to_remove:
  126. if self.notify_deletion:
  127. print("Autoremoving element from group '" + rm[0] + "'")
  128. self.removeItem(*rm)
  129. else:
  130. self._status[group] = state
  131. warnings.warn("Specified Group \""+group+"\" not in Elements", GroupWarning, stacklevel=2)
  132. def addMenuItem(self, group, item):
  133. """
  134. Deprecated. Use addItem.
  135. """
  136. self.addItem(group, item)
  137. def addButton(self, group, item):
  138. """
  139. Deprecated. Use addItem.
  140. """
  141. self.addItem(group, item)
  142. def addCheckbox(self, group, item):
  143. """
  144. Deprecated. Use addItem.
  145. """
  146. self.addItem(group, item)
  147. def removeItem(self, group, item):
  148. """
  149. Remove an element from a group
  150. :param group: (list or str) list of groups or groupname. if set to none: remove from all groups
  151. :param item: (list or item) list of items or item to remove
  152. :return: -
  153. """
  154. if group is None:
  155. group = list(self._objects.keys())
  156. groups = group if isinstance(group, list) else [group]
  157. items = item if isinstance(item, list) else [item]
  158. for gr in groups:
  159. #print(gr)
  160. if not gr in self._objects:
  161. # return
  162. continue
  163. for it in items:
  164. if it in self._objects[gr]:
  165. del self._objects[gr][self._objects[gr].index(it)]
  166. def removeGroup(self, group):
  167. """
  168. Remove a group from GroupedObjects. If the group is not registered, a warning will be raised.
  169. :param group: (str) the group to remove
  170. :return:
  171. """
  172. if group in self._objects:
  173. del self._objects[group]
  174. else:
  175. warnings.warn("Group was not registered - Nothing removed", GroupWarning, stacklevel=2)
  176. def emptyGroup(self, group):
  177. """
  178. Unregister all elements from group. (This will delete the group and recreate it.
  179. :param group: (str) the group to clean out.
  180. :return: -
  181. """
  182. self.removeGroup(group)
  183. self.createEmptyGroup(group)
  184. def getElements(self, group):
  185. """
  186. Get the elements of a group as list.
  187. :param group: (str) the gorup you want the elements of
  188. :return: (list) Elements in group
  189. """
  190. if group in self._objects:
  191. return self._objects[group]
  192. else:
  193. return []
  194. def isEnabled(self, group):
  195. """
  196. Check if a group is enabled.
  197. :param group: (str) the gorup to check.
  198. :return: (bool) State of group
  199. """
  200. if group in self._status:
  201. return self._status[group]
  202. else:
  203. return True # Default for elements is enabled
  204. class LivePlotWindows():
  205. """
  206. Container class to hold open LivePlotWindows.
  207. Added LivePlotWindows will automatically be plotted to on the event of new data.
  208. """
  209. def __init__(self):
  210. self.plotWindows = {}
  211. def addWindow(self, board_id, window):
  212. """
  213. Register a Window.
  214. :param window: (PlotWidget) The window to be added.
  215. :return: -
  216. """
  217. if board_id in self.plotWindows:
  218. self.plotWindows[board_id].append(window)
  219. else:
  220. self.plotWindows[board_id] = [window, ]
  221. def getWindows(self, board_id):
  222. """
  223. Get the list of registered plot windows.
  224. :return: (list) List of plotWindows
  225. """
  226. return self.plotWindows[board_id]
  227. def hasWindows(self, board_id):
  228. """
  229. Check if Windows are registered.
  230. :return: (bool) True if there are windows and False if not.
  231. """
  232. if board_id in self.plotWindows and len(self.plotWindows[board_id]) > 0:
  233. return True
  234. else:
  235. return False
  236. def removeWindow(self, board_id, window):
  237. """
  238. Remove a window from open plot windows
  239. :param window: the window to remove
  240. :return:
  241. """
  242. del self.plotWindows[board_id][self.plotWindows[board_id].index(window)]
  243. # Every Element is acessible through every Variable set here. Checkboxes, Buttons and MenuItems variables are set
  244. # to improve readability of the code. They refer to the same Object
  245. Elements = Checkboxes = Buttons = MenuItems = GroupedObjects()
  246. live_plot_windows = LivePlotWindows()
  247. cuda_windows = None