appProcess.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. # ##########################################################
  2. # FlatCAM: 2D Post-processing for Manufacturing #
  3. # http://flatcam.org #
  4. # Author: Juan Pablo Caram (c) #
  5. # Date: 2/5/2014 #
  6. # MIT Licence #
  7. # ##########################################################
  8. from appGUI.GUIElements import FlatCAMActivityView
  9. from PyQt5 import QtCore
  10. import weakref
  11. import gettext
  12. import appTranslation as fcTranslate
  13. import builtins
  14. fcTranslate.apply_language('strings')
  15. if '_' not in builtins.__dict__:
  16. _ = gettext.gettext
  17. # import logging
  18. # log = logging.getLogger('base2')
  19. # #log.setLevel(logging.DEBUG)
  20. # log.setLevel(logging.WARNING)
  21. # #log.setLevel(logging.INFO)
  22. # formatter = logging.Formatter('[%(levelname)s] %(message)s')
  23. # handler = logging.StreamHandler()
  24. # handler.setFormatter(formatter)
  25. # log.addHandler(handler)
  26. class FCProcess(object):
  27. app = None
  28. def __init__(self, descr):
  29. self.callbacks = {
  30. "done": []
  31. }
  32. self.descr = descr
  33. self.status = "Active"
  34. def __del__(self):
  35. self.done()
  36. def __enter__(self):
  37. pass
  38. def __exit__(self, exc_type, exc_val, exc_tb):
  39. if exc_type is not None:
  40. self.app.log.error("Abnormal termination of process!")
  41. self.app.log.error(exc_type)
  42. self.app.log.error(exc_val)
  43. self.app.log.error(exc_tb)
  44. self.done()
  45. def done(self):
  46. for fcn in self.callbacks["done"]:
  47. fcn(self)
  48. def connect(self, callback, event="done"):
  49. if callback not in self.callbacks[event]:
  50. self.callbacks[event].append(callback)
  51. def disconnect(self, callback, event="done"):
  52. try:
  53. self.callbacks[event].remove(callback)
  54. except ValueError:
  55. pass
  56. def set_status(self, status_string):
  57. self.status = status_string
  58. def status_msg(self):
  59. return self.descr
  60. class FCProcessContainer(object):
  61. """
  62. This is the process container, or controller (as in MVC)
  63. of the Process/Activity tracking.
  64. FCProcessContainer keeps weak references to the FCProcess'es
  65. such that their __del__ method is called when the user
  66. looses track of their reference.
  67. """
  68. app = None
  69. def __init__(self):
  70. self.procs = []
  71. def add(self, proc):
  72. self.procs.append(weakref.ref(proc))
  73. def new(self, descr):
  74. proc = FCProcess(descr)
  75. proc.connect(self.on_done, event="done")
  76. self.add(proc)
  77. self.on_change(proc)
  78. return proc
  79. def on_change(self, proc):
  80. pass
  81. def on_done(self, proc):
  82. self.remove(proc)
  83. def remove(self, proc):
  84. to_be_removed = []
  85. for pref in self.procs:
  86. if pref() == proc or pref() is None:
  87. to_be_removed.append(pref)
  88. for pref in to_be_removed:
  89. self.procs.remove(pref)
  90. class FCVisibleProcessContainer(QtCore.QObject, FCProcessContainer):
  91. something_changed = QtCore.pyqtSignal()
  92. # this will signal that the application is IDLE
  93. idle_flag = QtCore.pyqtSignal()
  94. def __init__(self, view):
  95. assert isinstance(view, FlatCAMActivityView), \
  96. "Expected a FlatCAMActivityView, got %s" % type(view)
  97. FCProcessContainer.__init__(self)
  98. QtCore.QObject.__init__(self)
  99. self.view = view
  100. self.text_to_display_in_activity = ''
  101. self.new_text = ' '
  102. self.something_changed.connect(self.update_view)
  103. def on_done(self, proc):
  104. # self.app.log.debug("FCVisibleProcessContainer.on_done()")
  105. super(FCVisibleProcessContainer, self).on_done(proc)
  106. self.something_changed.emit()
  107. def on_change(self, proc):
  108. # self.app.log.debug("FCVisibleProcessContainer.on_change()")
  109. super(FCVisibleProcessContainer, self).on_change(proc)
  110. # whenever there is a change update the message on activity
  111. self.text_to_display_in_activity = self.procs[0]().status_msg()
  112. self.something_changed.emit()
  113. def update_view(self):
  114. if len(self.procs) == 0:
  115. self.new_text = ''
  116. self.view.set_idle()
  117. self.idle_flag.emit()
  118. elif len(self.procs) == 1:
  119. self.view.set_busy(self.text_to_display_in_activity + self.new_text)
  120. else:
  121. self.view.set_busy("%d %s" % (len(self.procs), _("processes running.")))
  122. def update_view_text(self, new_text):
  123. # this has to be called after the method 'new' inherited by this class is called with a string text as param
  124. self.new_text = new_text
  125. if len(self.procs) == 1:
  126. self.view.set_busy(self.text_to_display_in_activity + self.new_text, no_movie=True)