FlatCAMCommon.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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
  27. item changes.
  28. """
  29. def __init__(self, *args, **kwargs):
  30. dict.__init__(self, *args, **kwargs)
  31. self.callback = lambda x: None
  32. def __setitem__(self, key, value):
  33. """
  34. Overridden __setitem__ method. Will emit 'changed(QString)'
  35. if the item was changed, with key as parameter.
  36. """
  37. if key in self and self.__getitem__(key) == value:
  38. return
  39. dict.__setitem__(self, key, value)
  40. self.callback(key)
  41. def update(self, *args, **kwargs):
  42. if len(args) > 1:
  43. raise TypeError("update expected at most 1 arguments, got %d" % len(args))
  44. other = dict(*args, **kwargs)
  45. for key in other:
  46. self[key] = other[key]
  47. def set_change_callback(self, callback):
  48. """
  49. Assigns a function as callback on item change. The callback
  50. will receive the key of the object that was changed.
  51. :param callback: Function to call on item change.
  52. :type callback: func
  53. :return: None
  54. """
  55. self.callback = callback
  56. class FCSignal:
  57. """
  58. Taken from here: https://blog.abstractfactory.io/dynamic-signals-in-pyqt/
  59. """
  60. def __init__(self):
  61. self.__subscribers = []
  62. def emit(self, *args, **kwargs):
  63. for subs in self.__subscribers:
  64. subs(*args, **kwargs)
  65. def connect(self, func):
  66. self.__subscribers.append(func)
  67. def disconnect(self, func):
  68. try:
  69. self.__subscribers.remove(func)
  70. except ValueError:
  71. print('Warning: function %s not removed '
  72. 'from signal %s' % (func, self))
  73. def color_variant(hex_color, bright_factor=1):
  74. """
  75. Takes a color in HEX format #FF00FF and produces a lighter or darker variant
  76. :param hex_color: color to change
  77. :param bright_factor: factor to change the color brightness [0 ... 1]
  78. :return: modified color
  79. """
  80. if len(hex_color) != 7:
  81. print("Color is %s, but needs to be in #FF00FF format. Returning original color." % hex_color)
  82. return hex_color
  83. if bright_factor > 1.0:
  84. bright_factor = 1.0
  85. if bright_factor < 0.0:
  86. bright_factor = 0.0
  87. rgb_hex = [hex_color[x:x + 2] for x in [1, 3, 5]]
  88. new_rgb = []
  89. for hex_value in rgb_hex:
  90. # adjust each color channel and turn it into a INT suitable as argument for hex()
  91. mod_color = round(int(hex_value, 16) * bright_factor)
  92. # make sure that each color channel has two digits without the 0x prefix
  93. mod_color_hex = str(hex(mod_color)[2:]).zfill(2)
  94. new_rgb.append(mod_color_hex)
  95. return "#" + "".join([i for i in new_rgb])