From ebdb2b3ca07abdfc5502a7779ec956834eb728bc Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Mon, 20 Jul 2020 19:21:17 +0300 Subject: [PATCH] - fixed a bug in the FlatCAMGerber.on_mark_cb_click_table() method when moving a Gerber object - added a way to remember the colors set for the Gerber objects; it will remember the order that they were loaded and set a color previously given --- CHANGELOG.md | 5 +++ Common.py | 79 +++++++++++++++++++++++++++++++++++++ appObjects/AppObject.py | 32 ++++++++++++++- appObjects/FlatCAMGerber.py | 6 ++- app_Main.py | 13 ++++++ defaults.py | 4 +- 6 files changed, 135 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9d3916d..52e753d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ CHANGELOG for FlatCAM beta ================================================= +20.07.2020 + +- fixed a bug in the FlatCAMGerber.on_mark_cb_click_table() method when moving a Gerber object +- added a way to remember the colors set for the Gerber objects; it will remember the order that they were loaded and set a color previously given + 18.07.2020 - added some icons in the Code Editor diff --git a/Common.py b/Common.py index a8c0b382..b850fe6f 100644 --- a/Common.py +++ b/Common.py @@ -19,6 +19,7 @@ from appGUI.VisPyVisuals import ShapeCollection from appTool import AppTool from copy import deepcopy +import collections import numpy as np @@ -81,6 +82,84 @@ class LoudDict(dict): self.callback = callback +class LoudUniqueList(list, collections.MutableSequence): + """ + A List with a callback for item changes, callback which returns the index where the items are added/modified. + A List that will allow adding only items that are not in the list. + """ + + def __init__(self, arg=None): + super().__init__() + self.callback = lambda x: None + + if not arg is None: + if isinstance(arg, list): + self.extend(arg) + else: + self.extend([arg]) + + def insert(self, i, v): + if v in self: + raise ValueError("One of the added items is already in the list.") + self.callback(i) + return super().insert(i, v) + + def append(self, v): + if v in self: + raise ValueError("One of the added items is already in the list.") + l = len(self) + self.callback(l) + return super().append(v) + + def extend(self, t): + for v in t: + if v in self: + raise ValueError("One of the added items is already in the list.") + l = len(self) + self.callback(l) + return super().extend(t) + + def __add__(self, t): # This is for something like `LoudUniqueList([1, 2, 3]) + list([4, 5, 6])`... + for v in t: + if v in self: + raise ValueError("One of the added items is already in the list.") + l = len(self) + self.callback(l) + return super().__add__(t) + + def __iadd__(self, t): # This is for something like `l = LoudUniqueList(); l += [1, 2, 3]` + for v in t: + if v in self: + raise ValueError("One of the added items is already in the list.") + l = len(self) + self.callback(l) + return super().__iadd__(t) + + def __setitem__(self, i, v): + try: + for v1 in v: + if v1 in self: + raise ValueError("One of the modified items is already in the list.") + except TypeError: + if v in self: + raise ValueError("One of the modified items is already in the list.") + if not v is None: + self.callback(i) + return super().__setitem__(i, v) + + def set_callback(self, callback): + """ + Assigns a function as callback on item change. The callback + will receive the index 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/ diff --git a/appObjects/AppObject.py b/appObjects/AppObject.py index 1358812a..5ec28ce0 100644 --- a/appObjects/AppObject.py +++ b/appObjects/AppObject.py @@ -193,14 +193,33 @@ class AppObject(QtCore.QObject): log.warning("AppObject.new_object() -> The object has no bounds properties. %s" % str(e)) return "fail" + # ############################################################################################################ + # Set the colors for the objects that have geometry + # ############################################################################################################ + if kind != 'document' and kind != 'script': try: if kind == 'excellon': obj.fill_color = self.app.defaults["excellon_plot_fill"] obj.outline_color = self.app.defaults["excellon_plot_line"] if kind == 'gerber': - obj.fill_color = self.app.defaults["gerber_plot_fill"] - obj.outline_color = self.app.defaults["gerber_plot_line"] + group = self.app.collection.group_items["gerber"] + index = group.child_count() + + # when loading a Gerber object always create a color tuple (line color, fill_color) + # and add it to the self.app.defaults["gerber_color_list"] from where it will be picked and used + try: + colors = self.app.defaults["gerber_color_list"][index] + except IndexError: + obj.outline_color = self.app.defaults["gerber_plot_line"] + obj.fill_color = self.app.defaults["gerber_plot_fill"] + self.app.defaults["gerber_color_list"].insert(index, (obj.outline_color, obj.fill_color)) + colors = self.app.defaults["gerber_color_list"][index] + + new_line_color = colors[0] + new_color = colors[1] + obj.outline_color = new_line_color + obj.fill_color = new_color except Exception as e: log.warning("AppObject.new_object() -> setting colors error. %s" % str(e)) @@ -319,6 +338,7 @@ class AppObject(QtCore.QObject): :param auto_select: if the newly created object to be autoselected after creation :return: None """ + t0 = time.time() # DEBUG log.debug("on_object_created()") @@ -330,6 +350,10 @@ class AppObject(QtCore.QObject): # self.app.inform.emit('[selected] %s created & selected: %s' % # (str(obj.kind).capitalize(), str(obj.options['name']))) + + # ############################################################################################################# + # ###################### Set colors for the message in the Status Bar ####################################### + # ############################################################################################################# if obj.kind == 'gerber': self.app.inform.emit('[selected] {kind} {tx}: {name}'.format( kind=obj.kind.capitalize(), @@ -367,7 +391,9 @@ class AppObject(QtCore.QObject): name=str(obj.options['name']), tx=_("created/selected")) ) + # ############################################################################################################# # update the SHELL auto-completer model with the name of the new object + # ############################################################################################################# self.app.shell._edit.set_model_data(self.app.myKeywords) if auto_select: @@ -382,6 +408,8 @@ class AppObject(QtCore.QObject): with self.app.proc_container.new(_("Plotting")): if t_obj.kind == 'cncjob': t_obj.plot(kind=self.app.defaults["cncjob_plot_kind"]) + if t_obj.kind == 'gerber': + t_obj.plot(color=t_obj.outline_color, face_color=t_obj.fill_color) else: t_obj.plot() diff --git a/appObjects/FlatCAMGerber.py b/appObjects/FlatCAMGerber.py index 7c161f48..222ac9d5 100644 --- a/appObjects/FlatCAMGerber.py +++ b/appObjects/FlatCAMGerber.py @@ -1042,7 +1042,11 @@ class GerberObject(FlatCAMObj, Gerber): self.marked_rows[:] = [] - aperture = self.ui.apertures_table.item(cw_row, 1).text() + try: + aperture = self.ui.apertures_table.item(cw_row, 1).text() + except AttributeError: + self.ui_connect() + return if self.ui.apertures_table.cellWidget(cw_row, 5).isChecked(): self.marked_rows.append(True) diff --git a/app_Main.py b/app_Main.py index 086320df..1a667808 100644 --- a/app_Main.py +++ b/app_Main.py @@ -10127,6 +10127,19 @@ class App(QtCore.QObject): update_colors=(new_color, new_line_color) ) + # make sure to set the color in the Gerber colors storage self.defaults["gerber_color_list"] + group = self.collection.group_items["gerber"] + group_index = self.collection.index(group.row(), 0, QtCore.QModelIndex()) + + new_c = (new_color, new_line_color) + + for sel_obj in sel_obj_list: + if sel_obj.kind == 'gerber': + item = sel_obj.item + item_index = self.collection.index(item.row(), 0, group_index) + idx = item_index.row() + self.defaults["gerber_color_list"][idx] = new_c + def generate_cnc_job(self, objects): """ Slot that will be called by clicking an entry in the contextual menu generated in the Project Tab tree diff --git a/defaults.py b/defaults.py index e14fa508..647988be 100644 --- a/defaults.py +++ b/defaults.py @@ -2,7 +2,7 @@ import os import stat import sys from copy import deepcopy -from Common import LoudDict +from Common import LoudDict, LoudUniqueList from camlib import to_dict, CNCjob, Geometry import simplejson import logging @@ -156,6 +156,8 @@ class FlatCAMDefaults: "gerber_plot": True, "gerber_solid": True, "gerber_multicolored": False, + "gerber_color_list": LoudUniqueList(), + "gerber_circle_steps": 64, "gerber_use_buffer_for_union": True, "gerber_clean_apertures": True,