# ########################################################## # FlatCAM: 2D Post-processing for Manufacturing # # http://flatcam.org # # Author: Juan Pablo Caram (c) # # Date: 2/5/2014 # # MIT Licence # # ########################################################## # ########################################################## # File Modified (major mod): Marius Adrian Stanciu # # Date: 11/4/2019 # # ########################################################## import gettext import FlatCAMTranslation as fcTranslate import builtins fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext class GracefulException(Exception): # Graceful Exception raised when the user is requesting to cancel the current threaded task def __init__(self): super().__init__() def __str__(self): return '\n\n%s' % _("The user requested a graceful exit of the current task.") class LoudDict(dict): """ A Dictionary with a callback for item changes. """ def __init__(self, *args, **kwargs): dict.__init__(self, *args, **kwargs) self.callback = lambda x: None def __setitem__(self, key, value): """ Overridden __setitem__ method. Will emit 'changed(QString)' if the item was changed, with key as parameter. """ if key in self and self.__getitem__(key) == value: return dict.__setitem__(self, key, value) self.callback(key) def update(self, *args, **kwargs): if len(args) > 1: raise TypeError("update expected at most 1 arguments, got %d" % len(args)) other = dict(*args, **kwargs) for key in other: self[key] = other[key] def set_change_callback(self, callback): """ Assigns a function as callback on item change. The callback will receive the key of the object that was changed. :param callback: Function to call on item change. :type callback: func :return: None """ self.callback = callback class FCSignal: """ Taken from here: https://blog.abstractfactory.io/dynamic-signals-in-pyqt/ """ def __init__(self): self.__subscribers = [] def emit(self, *args, **kwargs): for subs in self.__subscribers: subs(*args, **kwargs) def connect(self, func): self.__subscribers.append(func) def disconnect(self, func): try: self.__subscribers.remove(func) except ValueError: print('Warning: function %s not removed ' 'from signal %s' % (func, self)) def color_variant(hex_color, bright_factor=1): """ Takes a color in HEX format #FF00FF and produces a lighter or darker variant :param hex_color: color to change :param bright_factor: factor to change the color brightness [0 ... 1] :return: modified color """ if len(hex_color) != 7: print("Color is %s, but needs to be in #FF00FF format. Returning original color." % hex_color) return hex_color if bright_factor > 1.0: bright_factor = 1.0 if bright_factor < 0.0: bright_factor = 0.0 rgb_hex = [hex_color[x:x + 2] for x in [1, 3, 5]] new_rgb = [] for hex_value in rgb_hex: # adjust each color channel and turn it into a INT suitable as argument for hex() mod_color = round(int(hex_value, 16) * bright_factor) # make sure that each color channel has two digits without the 0x prefix mod_color_hex = str(hex(mod_color)[2:]).zfill(2) new_rgb.append(mod_color_hex) return "#" + "".join([i for i in new_rgb])