FlatCAMCommon.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. # ##########################################################
  9. # File Modified (major mod): Marius Adrian Stanciu #
  10. # Date: 11/4/2019 #
  11. # ##########################################################
  12. import gettext
  13. import FlatCAMTranslation as fcTranslate
  14. import builtins
  15. fcTranslate.apply_language('strings')
  16. if '_' not in builtins.__dict__:
  17. _ = gettext.gettext
  18. class GracefulException(Exception):
  19. # Graceful Exception raised when the user is requesting to cancel the current threaded task
  20. def __init__(self):
  21. super().__init__()
  22. def __str__(self):
  23. return '\n\n%s' % _("The user requested a graceful exit of the current task.")
  24. class LoudDict(dict):
  25. """
  26. A Dictionary with a callback for item changes.
  27. """
  28. def __init__(self, *args, **kwargs):
  29. dict.__init__(self, *args, **kwargs)
  30. self.callback = lambda x: None
  31. def __setitem__(self, key, value):
  32. """
  33. Overridden __setitem__ method. Will emit 'changed(QString)' if the item was changed, with key as parameter.
  34. """
  35. if key in self and self.__getitem__(key) == value:
  36. return
  37. dict.__setitem__(self, key, value)
  38. self.callback(key)
  39. def update(self, *args, **kwargs):
  40. if len(args) > 1:
  41. raise TypeError("update expected at most 1 arguments, got %d" % len(args))
  42. other = dict(*args, **kwargs)
  43. for key in other:
  44. self[key] = other[key]
  45. def set_change_callback(self, callback):
  46. """
  47. Assigns a function as callback on item change. The callback
  48. will receive the key of the object that was changed.
  49. :param callback: Function to call on item change.
  50. :type callback: func
  51. :return: None
  52. """
  53. self.callback = callback
  54. class FCSignal:
  55. """
  56. Taken from here: https://blog.abstractfactory.io/dynamic-signals-in-pyqt/
  57. """
  58. def __init__(self):
  59. self.__subscribers = []
  60. def emit(self, *args, **kwargs):
  61. for subs in self.__subscribers:
  62. subs(*args, **kwargs)
  63. def connect(self, func):
  64. self.__subscribers.append(func)
  65. def disconnect(self, func):
  66. try:
  67. self.__subscribers.remove(func)
  68. except ValueError:
  69. print('Warning: function %s not removed '
  70. 'from signal %s' % (func, self))
  71. def color_variant(hex_color, bright_factor=1):
  72. """
  73. Takes a color in HEX format #FF00FF and produces a lighter or darker variant
  74. :param hex_color: color to change
  75. :param bright_factor: factor to change the color brightness [0 ... 1]
  76. :return: modified color
  77. """
  78. if len(hex_color) != 7:
  79. print("Color is %s, but needs to be in #FF00FF format. Returning original color." % hex_color)
  80. return hex_color
  81. if bright_factor > 1.0:
  82. bright_factor = 1.0
  83. if bright_factor < 0.0:
  84. bright_factor = 0.0
  85. rgb_hex = [hex_color[x:x + 2] for x in [1, 3, 5]]
  86. new_rgb = []
  87. for hex_value in rgb_hex:
  88. # adjust each color channel and turn it into a INT suitable as argument for hex()
  89. mod_color = round(int(hex_value, 16) * bright_factor)
  90. # make sure that each color channel has two digits without the 0x prefix
  91. mod_color_hex = str(hex(mod_color)[2:]).zfill(2)
  92. new_rgb.append(mod_color_hex)
  93. return "#" + "".join([i for i in new_rgb])