diff --git a/FlatCAMApp.py b/FlatCAMApp.py index e3b9c219..a6b3cf01 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -3459,14 +3459,14 @@ class App(QtCore.QObject): # here it is done the object plotting def worker_task(t_obj): - with self.proc_container.new("Plotting"): - if isinstance(t_obj, FlatCAMCNCjob): - t_obj.plot(kind=self.defaults["cncjob_plot_kind"]) - else: - t_obj.plot() - t1 = time.time() # DEBUG - self.log.debug("%f seconds adding object and plotting." % (t1 - t0)) - self.object_plotted.emit(t_obj) + # with self.proc_container.new(_("Plotting")): + if isinstance(t_obj, FlatCAMCNCjob): + t_obj.plot(kind=self.defaults["cncjob_plot_kind"]) + else: + t_obj.plot() + t1 = time.time() # DEBUG + self.log.debug("%f seconds adding object and plotting." % (t1 - t0)) + self.object_plotted.emit(t_obj) # Send to worker # self.worker.add_task(worker_task, [self]) diff --git a/FlatCAMObj.py b/FlatCAMObj.py index d3c4b253..8652d4e3 100644 --- a/FlatCAMObj.py +++ b/FlatCAMObj.py @@ -348,16 +348,16 @@ class FlatCAMObj(QtCore.QObject): log.debug("FlatCAMObj.visible()") def worker_task(app_obj): - app_obj.shapes.visible = value + self.shapes.visible = value # Not all object types has annotations try: - app_obj.annotation.visible = value + self.annotation.visible = value except Exception as e: pass if threaded is False: - worker_task(app_obj=self) + worker_task(app_obj=self.app) else: self.app.worker_task.emit({'fcn': worker_task, 'params': [self]}) @@ -1179,39 +1179,40 @@ class FlatCAMGerber(FlatCAMObj, Gerber): color[3] = 1 return color - try: - if self.options["solid"]: - for g in geometry: - if type(g) == Polygon or type(g) == LineString: - self.add_shape(shape=g, color=color, - face_color=random_color() if self.options['multicolored'] - else face_color, visible=self.options['plot']) - elif type(g) == Point: - pass - else: - try: - for el in g: - self.add_shape(shape=el, color=color, - face_color=random_color() if self.options['multicolored'] - else face_color, visible=self.options['plot']) - except TypeError: + with self.app.proc_container.new(_("Plotting")): + try: + if self.options["solid"]: + for g in geometry: + if type(g) == Polygon or type(g) == LineString: self.add_shape(shape=g, color=color, face_color=random_color() if self.options['multicolored'] else face_color, visible=self.options['plot']) - else: - for g in geometry: - if type(g) == Polygon or type(g) == LineString: - self.add_shape(shape=g, color=random_color() if self.options['multicolored'] else 'black', - visible=self.options['plot']) - elif type(g) == Point: - pass - else: - for el in g: - self.add_shape(shape=el, color=random_color() if self.options['multicolored'] else 'black', + elif type(g) == Point: + pass + else: + try: + for el in g: + self.add_shape(shape=el, color=color, + face_color=random_color() if self.options['multicolored'] + else face_color, visible=self.options['plot']) + except TypeError: + self.add_shape(shape=g, color=color, + face_color=random_color() if self.options['multicolored'] + else face_color, visible=self.options['plot']) + else: + for g in geometry: + if type(g) == Polygon or type(g) == LineString: + self.add_shape(shape=g, color=random_color() if self.options['multicolored'] else 'black', visible=self.options['plot']) - self.shapes.redraw() - except (ObjectDeleted, AttributeError): - self.shapes.clear(update=True) + elif type(g) == Point: + pass + else: + for el in g: + self.add_shape(shape=el, color=random_color() if self.options['multicolored'] else 'black', + visible=self.options['plot']) + self.shapes.redraw() + except (ObjectDeleted, AttributeError): + self.shapes.clear(update=True) # experimental plot() when the solid_geometry is stored in the self.apertures def plot_aperture(self, **kwargs): @@ -2928,28 +2929,29 @@ class FlatCAMExcellon(FlatCAMObj, Excellon): # except (ObjectDeleted, AttributeError, KeyError): # self.shapes.clear(update=True) - # this stays for compatibility reasons, in case we try to open old projects - try: - __ = iter(self.solid_geometry) - except TypeError: - self.solid_geometry = [self.solid_geometry] + with self.app.proc_container.new(_("Plotting")): + # this stays for compatibility reasons, in case we try to open old projects + try: + __ = iter(self.solid_geometry) + except TypeError: + self.solid_geometry = [self.solid_geometry] - try: - # Plot Excellon (All polygons?) - if self.options["solid"]: - for geo in self.solid_geometry: - self.add_shape(shape=geo, color='#750000BF', face_color='#C40000BF', - visible=self.options['plot'], - layer=2) - else: - for geo in self.solid_geometry: - self.add_shape(shape=geo.exterior, color='red', visible=self.options['plot']) - for ints in geo.interiors: - self.add_shape(shape=ints, color='orange', visible=self.options['plot']) + try: + # Plot Excellon (All polygons?) + if self.options["solid"]: + for geo in self.solid_geometry: + self.add_shape(shape=geo, color='#750000BF', face_color='#C40000BF', + visible=self.options['plot'], + layer=2) + else: + for geo in self.solid_geometry: + self.add_shape(shape=geo.exterior, color='red', visible=self.options['plot']) + for ints in geo.interiors: + self.add_shape(shape=ints, color='orange', visible=self.options['plot']) - self.shapes.redraw() - except (ObjectDeleted, AttributeError): - self.shapes.clear(update=True) + self.shapes.redraw() + except (ObjectDeleted, AttributeError): + self.shapes.clear(update=True) class FlatCAMGeometry(FlatCAMObj, Geometry): @@ -6039,32 +6041,33 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob): if not FlatCAMObj.plot(self): return - visible = visible if visible else self.options['plot'] + with self.app.proc_container.new(_("Plotting")): + visible = visible if visible else self.options['plot'] - if self.ui.annotation_cb.get_value() and self.ui.plot_cb.get_value(): - self.text_col.enabled = True - else: - self.text_col.enabled = False - self.annotation.redraw() - - try: - if self.multitool is False: # single tool usage - try: - dia_plot = float(self.options["tooldia"]) - except ValueError: - # we may have a tuple with only one element and a comma - dia_plot = [float(el) for el in self.options["tooldia"].split(',') if el != ''][0] - self.plot2(dia_plot, obj=self, visible=visible, kind=kind) + if self.ui.annotation_cb.get_value() and self.ui.plot_cb.get_value(): + self.text_col.enabled = True else: - # multiple tools usage - for tooluid_key in self.cnc_tools: - tooldia = float('%.4f' % float(self.cnc_tools[tooluid_key]['tooldia'])) - gcode_parsed = self.cnc_tools[tooluid_key]['gcode_parsed'] - self.plot2(tooldia=tooldia, obj=self, visible=visible, gcode_parsed=gcode_parsed, kind=kind) - self.shapes.redraw() - except (ObjectDeleted, AttributeError): - self.shapes.clear(update=True) - self.annotation.clear(update=True) + self.text_col.enabled = False + self.annotation.redraw() + + try: + if self.multitool is False: # single tool usage + try: + dia_plot = float(self.options["tooldia"]) + except ValueError: + # we may have a tuple with only one element and a comma + dia_plot = [float(el) for el in self.options["tooldia"].split(',') if el != ''][0] + self.plot2(dia_plot, obj=self, visible=visible, kind=kind) + else: + # multiple tools usage + for tooluid_key in self.cnc_tools: + tooldia = float('%.4f' % float(self.cnc_tools[tooluid_key]['tooldia'])) + gcode_parsed = self.cnc_tools[tooluid_key]['gcode_parsed'] + self.plot2(tooldia=tooldia, obj=self, visible=visible, gcode_parsed=gcode_parsed, kind=kind) + self.shapes.redraw() + except (ObjectDeleted, AttributeError): + self.shapes.clear(update=True) + self.annotation.clear(update=True) def on_annotation_change(self): if self.ui.annotation_cb.get_value(): diff --git a/FlatCAMProcess.py b/FlatCAMProcess.py index a2972ddb..f28b5a66 100644 --- a/FlatCAMProcess.py +++ b/FlatCAMProcess.py @@ -10,6 +10,13 @@ from flatcamGUI.FlatCAMGUI import FlatCAMActivityView from PyQt5 import QtCore import weakref +import gettext +import FlatCAMTranslation as fcTranslate +import builtins + +fcTranslate.apply_language('strings') +if '_' not in builtins.__dict__: + _ = gettext.gettext # import logging @@ -131,6 +138,9 @@ class FCVisibleProcessContainer(QtCore.QObject, FCProcessContainer): self.view = view + self.text_to_display_in_activity = '' + self.new_text = ' ' + self.something_changed.connect(self.update_view) def on_done(self, proc): @@ -143,14 +153,23 @@ class FCVisibleProcessContainer(QtCore.QObject, FCProcessContainer): # self.app.log.debug("FCVisibleProcessContainer.on_change()") super(FCVisibleProcessContainer, self).on_change(proc) + # whenever there is a change update the message on activity + self.text_to_display_in_activity = self.procs[0]().status_msg() + self.something_changed.emit() def update_view(self): if len(self.procs) == 0: self.view.set_idle() + self.new_text = '' elif len(self.procs) == 1: - self.view.set_busy(self.procs[0]().status_msg()) - + self.view.set_busy(self.text_to_display_in_activity + self.new_text) else: - self.view.set_busy("%d processes running." % len(self.procs)) + self.view.set_busy("%d %s" % (len(self.procs), _("processes running."))) + + def update_view_text(self, new_text): + # this has to be called after the method 'new' inherited by this class is called with a string text as param + self.new_text = new_text + if len(self.procs) == 1: + self.view.set_busy(self.text_to_display_in_activity + self.new_text) diff --git a/README.md b/README.md index 42deca61..35da56be 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ CAD program, and create G-Code for Isolation routing. - remade visibility threaded - reimplemented the thread listening for new FlatCAM process starting with args so it is no longer subclassed but using the moveToThread function - added percentage display for work done in NCC Tool +- added percentage display for work done in Paint Tool +- some fixes and prepared the activity monitor area to receive updated texts 5.09.2019 diff --git a/flatcamTools/ToolNonCopperClear.py b/flatcamTools/ToolNonCopperClear.py index 2ed66d9c..8b20f442 100644 --- a/flatcamTools/ToolNonCopperClear.py +++ b/flatcamTools/ToolNonCopperClear.py @@ -1637,11 +1637,10 @@ class NonCopperClear(FlatCAMTool, Gerber): area = MultiPolygon([area]) # variables to display the percentage of work done - step = int(len(area.geoms) / 100) + geo_len = len(area.geoms) disp_number = 0 old_disp_number = 0 - log.warning("Total number of polygons to be cleared. %s" % str(len(area.geoms))) - log.warning("Step: %d" % step) + log.warning("Total number of polygons to be cleared. %s" % str(geo_len)) if area.geoms: if len(area.geoms) > 0: @@ -1687,10 +1686,10 @@ class NonCopperClear(FlatCAMTool, Gerber): continue pol_nr += 1 - disp_number = int(pol_nr / step) + disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 99])) # log.debug("Polygons cleared: %d" % pol_nr) - if disp_number > old_disp_number and disp_number <= 100: + if old_disp_number < disp_number <= 100: app_obj.inform.emit( '[success] %s %s%s %s: %d%%' % (_('Non-Copper Clearing with tool diameter = '), str(tool), @@ -1937,11 +1936,10 @@ class NonCopperClear(FlatCAMTool, Gerber): allparts[:] = [] # variables to display the percentage of work done - step = int(len(area.geoms) / 100) + geo_len = len(area.geoms) disp_number = 0 old_disp_number = 0 - log.warning("Total number of polygons to be cleared. %s" % str(len(area.geoms))) - log.warning("Step: %d" % step) + log.warning("Total number of polygons to be cleared. %s" % str(geo_len)) if area.geoms: if len(area.geoms) > 0: @@ -1995,7 +1993,7 @@ class NonCopperClear(FlatCAMTool, Gerber): rest_geo.append(poly) pol_nr += 1 - disp_number = int(pol_nr / step) + disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 99])) # log.debug("Polygons cleared: %d" % pol_nr) if disp_number > old_disp_number and disp_number <= 100: diff --git a/flatcamTools/ToolPaint.py b/flatcamTools/ToolPaint.py index bbbdfd51..7dd164b1 100644 --- a/flatcamTools/ToolPaint.py +++ b/flatcamTools/ToolPaint.py @@ -1497,6 +1497,8 @@ class ToolPaint(FlatCAMTool, Gerber): # assert isinstance(geo_obj, FlatCAMGeometry), \ # "Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj) + log.debug("Paint Tool. Normal painting all task started.") + tool_dia = None if order == 'fwd': sorted_tools.sort(reverse=False) @@ -1520,6 +1522,14 @@ class ToolPaint(FlatCAMTool, Gerber): geo_obj.solid_geometry = [] for tool_dia in sorted_tools: + log.debug("Starting geometry processing for tool: %s" % str(tool_dia)) + app_obj.inform.emit( + '[success] %s %s%s %s: %d%%' % (_('Painting with tool diameter = '), + str(tool_dia), + self.units.lower(), + _('started. Progress'), + 0) + ) # find the tooluid associated with the current tool_dia so we know where to add the tool solid_geometry for k, v in tools_storage.items(): @@ -1527,7 +1537,15 @@ class ToolPaint(FlatCAMTool, Gerber): current_uid = int(k) break - for geo in recurse(obj.solid_geometry): + painted_area = recurse(obj.solid_geometry) + # variables to display the percentage of work done + geo_len = len(painted_area) + disp_number = 0 + old_disp_number = 0 + log.warning("Total number of polygons to be cleared. %s" % str(geo_len)) + + pol_nr = 0 + for geo in painted_area: try: # Polygons are the only really paintable geometries, lines in theory have no area to be painted if not isinstance(geo, Polygon): @@ -1570,6 +1588,21 @@ class ToolPaint(FlatCAMTool, Gerber): "Or a different Method of paint\n%s") % str(e)) return + pol_nr += 1 + disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 99])) + # log.debug("Polygons cleared: %d" % pol_nr) + + if old_disp_number < disp_number <= 100: + app_obj.inform.emit( + '[success] %s %s%s %s: %d%%' % (_('Painting with tool diameter = '), + str(tool_dia), + self.units.lower(), + _('started. Progress'), + disp_number) + ) + old_disp_number = disp_number + # log.debug("Polygons cleared: %d. Percentage done: %d%%" % (pol_nr, disp_number)) + # add the solid_geometry to the current too in self.paint_tools (tools_storage) # dictionary and then reset the temporary list that stored that solid_geometry tools_storage[current_uid]['solid_geometry'] = deepcopy(total_geometry) @@ -1618,6 +1651,8 @@ class ToolPaint(FlatCAMTool, Gerber): assert isinstance(geo_obj, FlatCAMGeometry), \ "Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj) + log.debug("Paint Tool. Rest machining painting all task started.") + tool_dia = None sorted_tools.sort(reverse=True) @@ -1636,7 +1671,17 @@ class ToolPaint(FlatCAMTool, Gerber): return for tool_dia in sorted_tools: - for geo in recurse(obj.solid_geometry): + log.debug("Starting geometry processing for tool: %s" % str(tool_dia)) + + painted_area = recurse(obj.solid_geometry) + # variables to display the percentage of work done + geo_len = int(len(painted_area) / 100) + disp_number = 0 + old_disp_number = 0 + log.warning("Total number of polygons to be cleared. %s" % str(geo_len)) + + pol_nr = 0 + for geo in painted_area: try: geo = Polygon(geo) if not isinstance(geo, Polygon) else geo poly_buf = geo.buffer(-paint_margin) @@ -1670,6 +1715,21 @@ class ToolPaint(FlatCAMTool, Gerber): "Or a different Method of paint\n%s") % str(e)) return + pol_nr += 1 + disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 99])) + # log.debug("Polygons cleared: %d" % pol_nr) + + if old_disp_number < disp_number <= 100: + app_obj.inform.emit( + '[success] %s %s%s %s: %d%%' % (_('Painting with tool diameter = '), + str(tool_dia), + self.units.lower(), + _('started. Progress'), + disp_number) + ) + old_disp_number = disp_number + # log.debug("Polygons cleared: %d. Percentage done: %d%%" % (pol_nr, disp_number)) + # find the tooluid associated with the current tool_dia so we know where to add the tool solid_geometry for k, v in tools_storage.items(): if float('%.4f' % v['tooldia']) == float('%.4f' % tool_dia): @@ -1833,6 +1893,9 @@ class ToolPaint(FlatCAMTool, Gerber): def gen_paintarea(geo_obj, app_obj): # assert isinstance(geo_obj, FlatCAMGeometry), \ # "Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj) + + log.debug("Paint Tool. Normal painting area task started.") + tool_dia = None if order == 'fwd': sorted_tools.sort(reverse=False) @@ -1867,6 +1930,14 @@ class ToolPaint(FlatCAMTool, Gerber): geo_obj.solid_geometry = [] for tool_dia in sorted_tools: + log.debug("Starting geometry processing for tool: %s" % str(tool_dia)) + app_obj.inform.emit( + '[success] %s %s%s %s: %d%%' % (_('Painting with tool diameter = '), + str(tool_dia), + self.units.lower(), + _('started. Progress'), + 0) + ) # find the tooluid associated with the current tool_dia so we know where to add the tool solid_geometry for k, v in tools_storage.items(): @@ -1874,7 +1945,15 @@ class ToolPaint(FlatCAMTool, Gerber): current_uid = int(k) break - for geo in recurse(geo_to_paint): + painted_area = recurse(geo_to_paint) + # variables to display the percentage of work done + geo_len = len(painted_area) + disp_number = 0 + old_disp_number = 0 + log.warning("Total number of polygons to be cleared. %s" % str(geo_len)) + + pol_nr = 0 + for geo in painted_area: try: # Polygons are the only really paintable geometries, lines in theory have no area to be painted if not isinstance(geo, Polygon): @@ -1917,6 +1996,21 @@ class ToolPaint(FlatCAMTool, Gerber): "Or a different Method of paint\n%s") % str(e)) return + pol_nr += 1 + disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 99])) + # log.debug("Polygons cleared: %d" % pol_nr) + + if disp_number > old_disp_number and disp_number <= 100: + app_obj.inform.emit( + '[success] %s %s%s %s: %d%%' % (_('Painting with tool diameter = '), + str(tool_dia), + self.units.lower(), + _('started. Progress'), + disp_number) + ) + old_disp_number = disp_number + # log.debug("Polygons cleared: %d. Percentage done: %d%%" % (pol_nr, disp_number)) + # add the solid_geometry to the current too in self.paint_tools (tools_storage) # dictionary and then reset the temporary list that stored that solid_geometry tools_storage[current_uid]['solid_geometry'] = deepcopy(total_geometry) @@ -1965,6 +2059,8 @@ class ToolPaint(FlatCAMTool, Gerber): assert isinstance(geo_obj, FlatCAMGeometry), \ "Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj) + log.debug("Paint Tool. Rest machining painting area task started.") + tool_dia = None sorted_tools.sort(reverse=True) @@ -1983,7 +2079,24 @@ class ToolPaint(FlatCAMTool, Gerber): return for tool_dia in sorted_tools: - for geo in recurse(obj.solid_geometry): + log.debug("Starting geometry processing for tool: %s" % str(tool_dia)) + app_obj.inform.emit( + '[success] %s %s%s %s: %d%%' % (_('Painting with tool diameter = '), + str(tool_dia), + self.units.lower(), + _('started. Progress'), + 0) + ) + + painted_area = recurse(obj.solid_geometry) + # variables to display the percentage of work done + geo_len = len(painted_area) + disp_number = 0 + old_disp_number = 0 + log.warning("Total number of polygons to be cleared. %s" % str(geo_len)) + + pol_nr = 0 + for geo in painted_area: try: geo = Polygon(geo) if not isinstance(geo, Polygon) else geo poly_buf = geo.buffer(-paint_margin) @@ -2017,6 +2130,21 @@ class ToolPaint(FlatCAMTool, Gerber): "Or a different Method of paint\n%s") % str(e)) return + pol_nr += 1 + disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 99])) + # log.debug("Polygons cleared: %d" % pol_nr) + + if disp_number > old_disp_number and disp_number <= 100: + app_obj.inform.emit( + '[success] %s %s%s %s: %d%%' % (_('Painting with tool diameter = '), + str(tool_dia), + self.units.lower(), + _('started. Progress'), + disp_number) + ) + old_disp_number = disp_number + # log.debug("Polygons cleared: %d. Percentage done: %d%%" % (pol_nr, disp_number)) + # find the tooluid associated with the current tool_dia so we know where to add the tool solid_geometry for k, v in tools_storage.items(): if float('%.4f' % v['tooldia']) == float('%.4f' % tool_dia): diff --git a/flatcamTools/ToolPanelize.py b/flatcamTools/ToolPanelize.py index ea7fd4c7..94b9588a 100644 --- a/flatcamTools/ToolPanelize.py +++ b/flatcamTools/ToolPanelize.py @@ -620,6 +620,9 @@ class Panelize(FlatCAMTool): app_obj.log.debug("Found %s geometries. Creating a panel geometry cascaded union ..." % len(obj_fin.solid_geometry)) + self.app.inform.emit(_("Found %s geometries. Creating a final panel geometry ...") % + len(obj_fin.solid_geometry)) + obj_fin.solid_geometry = cascaded_union(obj_fin.solid_geometry) app_obj.log.debug("Finished creating a cascaded union for the panel.") @@ -639,7 +642,7 @@ class Panelize(FlatCAMTool): "Final panel has {col} columns and {row} rows").format( col=columns, row=rows)) - proc = self.app.proc_container.new(_("Generating panel ... Please wait.")) + proc = self.app.proc_container.new(_("Generating panel ...")) def job_thread(app_obj): try: