diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 7d89429b..074a3610 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -126,7 +126,7 @@ class App(QtCore.QObject): # ################## Version and VERSION DATE ############################## # ########################################################################## version = 8.98 - version_date = "2019/10/7" + version_date = "2019/10/13" beta = True engine = '3D' @@ -1245,7 +1245,8 @@ class App(QtCore.QObject): 'minoffset, multidepth, name, offset, opt_type, order, outname, overlap, ' 'passes, postamble, pp, ppname_e, ppname_g, preamble, radius, ref, rest, ' 'rows, shellvar_, scale_factor, spacing_columns, spacing_rows, spindlespeed, ' - 'toolchange_xy, use_threads, value, x, x0, x1, y, y0, y1, z_cut, z_move', + 'toolchange_xy, tooldia, use_threads, value, x, x0, x1, y, y0, y1, z_cut, ' + 'z_move', "script_autocompleter": True, "script_text": "", "script_plot": True, @@ -2189,7 +2190,7 @@ class App(QtCore.QObject): 'outname', 'overlap', 'passes', 'postamble', 'pp', 'ppname_e', 'ppname_g', 'preamble', 'radius', 'ref', 'rest', 'rows', 'shellvar_', 'scale_factor', 'spacing_columns', - 'spacing_rows', 'spindlespeed', 'toolchange_xy', 'use_threads', 'value', 'x', + 'spacing_rows', 'spindlespeed', 'toolchange_xy','tooldia', 'use_threads', 'value', 'x', 'x0', 'x1', 'y', 'y0', 'y1', 'z_cut', 'z_move' ] @@ -2386,6 +2387,10 @@ class App(QtCore.QObject): # #################################################################################### # ####################### Shell SETUP ################################################ # #################################################################################### + # this will hold the TCL instance + self.tcl = None + + self.init_tcl() self.shell = FCShell(self, version=self.version) self.shell._edit.set_model_data(self.myKeywords) @@ -2395,8 +2400,6 @@ class App(QtCore.QObject): self.shell.append_output("FlatCAM %s - " % self.version) self.shell.append_output(_("Type >help< to get started\n\n")) - self.init_tcl() - self.ui.shell_dock = QtWidgets.QDockWidget("FlatCAM TCL Shell") self.ui.shell_dock.setObjectName('Shell_DockWidget') self.ui.shell_dock.setWidget(self.shell) @@ -2445,7 +2448,7 @@ class App(QtCore.QObject): # install Bookmark Manager and populate bookmarks in the Help -> Bookmarks self.install_bookmarks() - self.book_dialog_tab = BookmarkManager(app=self, storage=self.defaults["global_bookmarks"], parent=self.ui) + self.book_dialog_tab = BookmarkManager(app=self, storage=self.defaults["global_bookmarks"]) # ### System Font Parsing ### # self.f_parse = ParseFont(self) @@ -2577,9 +2580,6 @@ class App(QtCore.QObject): # set the value used in the Windows Title self.engine = self.ui.general_defaults_form.general_app_group.ge_radio.get_value() - # this will hold the TCL instance - self.tcl = None - # ############################################################################### # ############# Save defaults to factory_defaults.FlatConfig file ############### # ############# It's done only once after install ############### @@ -3413,7 +3413,7 @@ class App(QtCore.QObject): Initialize the TCL Shell. A dock widget that holds the GUI interface to the FlatCAM command line. :return: None """ - if hasattr(self, 'tcl'): + if hasattr(self, 'tcl') and self.tcl is not None: # self.tcl = None # TODO we need to clean non default variables and procedures here # new object cannot be used here as it will not remember values created for next passes, diff --git a/README.md b/README.md index ddcd43a9..00f83a8d 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ CAD program, and create G-Code for Isolation routing. - more fixes in Rules Check Tool - optimized the Move Tool - added support for key-based panning in 3D graphic engine. Moving the mouse wheel while pressing the CTRL key will pan up-down and while pressing SHIFT key will pan left-right +- fixed a bug in NCC Tool and start trying to make the App responsive while the NCC tool is run in a non-threaded way +- fixed a GUI bug with the QMenuBar recently introduced 11.10.2019 diff --git a/camlib.py b/camlib.py index df9ab8e8..0c358489 100644 --- a/camlib.py +++ b/camlib.py @@ -7,6 +7,7 @@ # ########################################################## ## +from PyQt5 import QtWidgets from io import StringIO import numpy as np @@ -1273,6 +1274,9 @@ class Geometry(object): # graceful abort requested by the user raise FlatCAMApp.GracefulException + # provide the app with a way to process the GUI events when in a blocking loop + QtWidgets.QApplication.processEvents() + # Can only result in a Polygon or MultiPolygon current = current.buffer(-tooldia * (1 - overlap), int(int(steps_per_circle) / 4)) if current.area > 0: @@ -1362,6 +1366,9 @@ class Geometry(object): # graceful abort requested by the user raise FlatCAMApp.GracefulException + # provide the app with a way to process the GUI events when in a blocking loop + QtWidgets.QApplication.processEvents() + path = Point(seedpoint).buffer(radius, int(steps_per_circle / 4)).exterior path = path.intersection(path_margin) @@ -1459,6 +1466,9 @@ class Geometry(object): # graceful abort requested by the user raise FlatCAMApp.GracefulException + # provide the app with a way to process the GUI events when in a blocking loop + QtWidgets.QApplication.processEvents() + line = LineString([(left, y), (right, y)]) line = line.intersection(margin_poly) lines_trimmed.append(line) diff --git a/flatcamGUI/FlatCAMGUI.py b/flatcamGUI/FlatCAMGUI.py index 06a702d2..e818874a 100644 --- a/flatcamGUI/FlatCAMGUI.py +++ b/flatcamGUI/FlatCAMGUI.py @@ -43,8 +43,11 @@ class FlatCAMGUI(QtWidgets.QMainWindow): # ######### ## self.menu = self.menuBar() - # self.menu_toggle_nb = QtWidgets.QAction(QtGui.QIcon('share/notebook32.png'), "NB") - self.menu_toggle_nb = QtWidgets.QAction("NB") + self.menu_toggle_nb = QtWidgets.QAction(QtGui.QIcon('share/notebook32.png'), _("Toggle Panel")) + self.menu_toggle_nb.setToolTip( + _("Toggle Panel") + ) + # self.menu_toggle_nb = QtWidgets.QAction("NB") self.menu_toggle_nb.setCheckable(True) self.menu.addAction(self.menu_toggle_nb) diff --git a/flatcamGUI/PlotCanvas.py b/flatcamGUI/PlotCanvas.py index 21480b97..64836840 100644 --- a/flatcamGUI/PlotCanvas.py +++ b/flatcamGUI/PlotCanvas.py @@ -280,7 +280,6 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas): p2 = np.array(curr_pos)[:2] self.view.camera.pan(p2 - p1) - if self.fcapp.grid_status() == True: pos_canvas = self.translate_coords(curr_pos) pos = self.fcapp.geo_editor.snap(pos_canvas[0], pos_canvas[1]) diff --git a/flatcamTools/ToolNonCopperClear.py b/flatcamTools/ToolNonCopperClear.py index e3d0d82e..ba7bd523 100644 --- a/flatcamTools/ToolNonCopperClear.py +++ b/flatcamTools/ToolNonCopperClear.py @@ -1358,12 +1358,16 @@ class NonCopperClear(FlatCAMTool, Gerber): :param rest: True if to use rest-machining :param tools_storage: whether to use the current tools_storage self.ncc_tools or a different one. Usage of the different one is related to when this function is called from a TcL command. + :param plot: if True after the job is finished the result will be plotted, else it will not. :param run_threaded: If True the method will be run in a threaded way suitable for GUI usage; if False it will run non-threaded for TclShell usage :return: """ - - proc = self.app.proc_container.new(_("Non-Copper clearing ...")) + if run_threaded: + proc = self.app.proc_container.new(_("Non-Copper clearing ...")) + else: + self.app.proc_container.view.set_busy(_("Non-Copper clearing ...")) + QtWidgets.QApplication.processEvents() # ##################################################################### # ####### Read the parameters ######################################### @@ -1526,6 +1530,10 @@ class NonCopperClear(FlatCAMTool, Gerber): assert isinstance(geo_obj, FlatCAMGeometry), \ "Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj) + # provide the app with a way to process the GUI events when in a blocking loop + if not run_threaded: + QtWidgets.QApplication.processEvents() + log.debug("NCC Tool. Normal copper clearing task started.") self.app.inform.emit(_("NCC Tool. Finished non-copper polygons. Normal copper clearing task started.")) @@ -1604,6 +1612,9 @@ class NonCopperClear(FlatCAMTool, Gerber): else: try: for geo_elem in isolated_geo: + # provide the app with a way to process the GUI events when in a blocking loop + QtWidgets.QApplication.processEvents() + if self.app.abort_flag: # graceful abort requested by the user raise FlatCAMApp.GracefulException @@ -1709,6 +1720,9 @@ class NonCopperClear(FlatCAMTool, Gerber): # graceful abort requested by the user raise FlatCAMApp.GracefulException + # provide the app with a way to process the GUI events when in a blocking loop + QtWidgets.QApplication.processEvents() + app_obj.inform.emit( '[success] %s %s%s %s' % (_('NCC Tool clearing with tool diameter = '), str(tool), @@ -1743,6 +1757,9 @@ class NonCopperClear(FlatCAMTool, Gerber): if len(area.geoms) > 0: pol_nr = 0 for p in area.geoms: + # provide the app with a way to process the GUI events when in a blocking loop + QtWidgets.QApplication.processEvents() + if self.app.abort_flag: # graceful abort requested by the user raise FlatCAMApp.GracefulException @@ -1879,6 +1896,10 @@ class NonCopperClear(FlatCAMTool, Gerber): log.debug("NCC Tool. Rest machining copper clearing task started.") app_obj.inform.emit('_(NCC Tool. Rest machining copper clearing task started.') + # provide the app with a way to process the GUI events when in a blocking loop + if not run_threaded: + QtWidgets.QApplication.processEvents() + # a flag to signal that the isolation is broken by the bounding box in 'area' and 'box' cases # will store the number of tools for which the isolation is broken warning_flag = 0 @@ -1934,6 +1955,9 @@ class NonCopperClear(FlatCAMTool, Gerber): else: try: for geo_elem in isolated_geo: + # provide the app with a way to process the GUI events when in a blocking loop + QtWidgets.QApplication.processEvents() + if self.app.abort_flag: # graceful abort requested by the user raise FlatCAMApp.GracefulException @@ -2062,6 +2086,9 @@ class NonCopperClear(FlatCAMTool, Gerber): # Area to clear for poly in cleared_by_last_tool: + # provide the app with a way to process the GUI events when in a blocking loop + QtWidgets.QApplication.processEvents() + if self.app.abort_flag: # graceful abort requested by the user raise FlatCAMApp.GracefulException @@ -2098,6 +2125,9 @@ class NonCopperClear(FlatCAMTool, Gerber): raise FlatCAMApp.GracefulException if p is not None: + # provide the app with a way to process the GUI events when in a blocking loop + QtWidgets.QApplication.processEvents() + if isinstance(p, Polygon): try: if ncc_method == 'standard': @@ -2124,6 +2154,9 @@ class NonCopperClear(FlatCAMTool, Gerber): elif isinstance(p, MultiPolygon): for poly in p: if poly is not None: + # provide the app with a way to process the GUI events when in a blocking loop + QtWidgets.QApplication.processEvents() + try: if ncc_method == 'standard': cp = self.clear_polygon(poly, tool_used, @@ -2235,13 +2268,19 @@ class NonCopperClear(FlatCAMTool, Gerber): else: app_obj.new_object("geometry", name, gen_clear_area, plot=plot) except FlatCAMApp.GracefulException: - proc.done() + if run_threaded: + proc.done() return except Exception as e: - proc.done() + if run_threaded: + proc.done() traceback.print_stack() return - proc.done() + if run_threaded: + proc.done() + else: + app_obj.proc_container.view.set_idle() + # focus on Selected Tab self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab) @@ -2630,6 +2669,9 @@ class NonCopperClear(FlatCAMTool, Gerber): except Exception as e: try: for el in target: + # provide the app with a way to process the GUI events when in a blocking loop + QtWidgets.QApplication.processEvents() + if self.app.abort_flag: # graceful abort requested by the user raise FlatCAMApp.GracefulException diff --git a/share/notebook16.png b/share/notebook16.png index f77ccaf7..70a2616f 100644 Binary files a/share/notebook16.png and b/share/notebook16.png differ diff --git a/share/notebook32.png b/share/notebook32.png index ebf69e04..b37197f6 100644 Binary files a/share/notebook32.png and b/share/notebook32.png differ