storage.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. from PyQt4 import QtCore
  2. class StorageError(Exception):
  3. """
  4. Simple Storage Error Base Class
  5. """
  6. pass
  7. class Storage(object):
  8. """
  9. Simple Class to store Values and Throw an error if a value is retrieved that has not been stored before.
  10. """
  11. def __init__(self, default=None):
  12. self._storage = {}
  13. if default:
  14. self._storage = default
  15. def setdefault(self, key, object):
  16. """
  17. Call setdefault on the underlying dictionary and return the result
  18. :param key: the key to call setdefault with
  19. :param object: the object to call setdefault with
  20. :return: the return value of setdefault of the dictionary
  21. """
  22. return self._storage.setdefault(key, object)
  23. def __setattr__(self, key, value):
  24. if key == '_storage':
  25. super(Storage, self).__setattr__(key, value)
  26. else:
  27. self._storage[key] = value
  28. def __getattr__(self, item):
  29. if item == '_storage':
  30. return super(Storage, self).__getattr__(item)
  31. if item in self._storage:
  32. return self._storage[item]
  33. else:
  34. raise StorageError("'"+item+"' Not saved in Storage")
  35. storage = Storage() # Container Object to use storage globally
  36. _board_specific_storages = {}
  37. def get_board_specific_storage(board_id):
  38. """
  39. Get the storage instance for a specific board
  40. :param board_id: the board to get the storage for
  41. :return: the instance of the storage for the given board
  42. """
  43. if board_id in _board_specific_storages:
  44. return _board_specific_storages[board_id]
  45. else:
  46. _board_specific_storages[board_id] = Storage()
  47. return _board_specific_storages[board_id]
  48. class ThreadStorage(object):
  49. """
  50. Wrapper for QThreads
  51. """
  52. def __init__(self):
  53. self._q_thread = None
  54. self._threaded_object = None
  55. self.running = False
  56. def register(self, threaded_object):
  57. """
  58. Register a class object to run in a QThread
  59. :param threaded_object: the class object
  60. :return:
  61. """
  62. del self._q_thread # start over
  63. self._q_thread = QtCore.QThread()
  64. self._q_thread.started.connect(self.__start)
  65. self._threaded_object = threaded_object
  66. def is_registered(self):
  67. """
  68. Check if a class for this thread is registered.
  69. :return:
  70. """
  71. return not (self._threaded_object is None)
  72. def __start(self):
  73. """
  74. This will be registered to the QThread started signal and will call the actual start_method
  75. :return:
  76. """
  77. self._start_method()
  78. def start(self, method_to_run_in_thread):
  79. """
  80. Move the class object to a QThread, connect the QThread.started signal to the given method of the
  81. class object
  82. :param method_to_run_in_thread: the method to start when starting the QThread
  83. :return:
  84. """
  85. self._threaded_object.moveToThread(self._q_thread)
  86. if isinstance(method_to_run_in_thread, str):
  87. self._start_method = getattr(self._threaded_object, method_to_run_in_thread)
  88. # self._q_thread.started.connect(getattr(self._threaded_object, method_to_run_in_thread))
  89. else:
  90. self._start_method = method_to_run_in_thread
  91. # self._q_thread.started.connect(method_to_run_in_thread)
  92. self._q_thread.start()
  93. self.running = True
  94. def quit(self):
  95. """
  96. Quit the thread class (if it has a method to quit)
  97. :return:
  98. """
  99. if hasattr(self._threaded_object, 'quit'):
  100. self._threaded_object.quit()
  101. def stop(self):
  102. """
  103. Call quit and wait to the underlying QThread
  104. :return:
  105. """
  106. self._q_thread.quit()
  107. self._q_thread.wait()
  108. self.running = False
  109. def __getattr__(self, item):
  110. """
  111. Get Attributes of the registered class object
  112. :param item: the item to get from the class object
  113. :return: the attribute of the class object
  114. """
  115. if not item.startswith('obj_'):
  116. raise AttributeError("If this was a call to an object of the threaded object, the call has to start with"
  117. "obj_.")
  118. if self._threaded_object is None:
  119. raise AttributeError("This Thread object does not have a threaded object. Register one first")
  120. return getattr(self._threaded_object, item[4:])
  121. def connect(self, signal, slot):
  122. """
  123. Connect signals of the class object to the given slots
  124. :param signal: the signal
  125. :param slot: the slot
  126. :return:
  127. """
  128. if isinstance(signal, str):
  129. getattr(self._threaded_object, signal).connect(slot)
  130. else:
  131. signal.connect(slot)
  132. def disconnect(self, *args):
  133. """
  134. Disconnect the given signals
  135. :param args: the signals to disconnect
  136. :return:
  137. """
  138. for signal in args:
  139. getattr(self._threaded_object, signal).disconnect()
  140. def init(self, *args, **kwargs):
  141. """
  142. call the threaded objects init method (not __init__) with the passed arguments
  143. :return:
  144. """
  145. self._threaded_object.init(*args, **kwargs)