Просмотр исходного кода

jpcgt/flatcam/Beta слито с Beta

Camellan 6 лет назад
Родитель
Сommit
490d359bb7
8 измененных файлов с 619 добавлено и 526 удалено
  1. 0 7
      FlatCAM.py
  2. 75 17
      FlatCAMApp.py
  3. 6 0
      README.md
  4. 285 278
      camlib.py
  5. 1 0
      config/configuration.txt
  6. 7 4
      flatcamTools/ToolShell.py
  7. BIN
      locale/pt_BR/LC_MESSAGES/strings.mo
  8. 245 220
      locale/pt_BR/LC_MESSAGES/strings.po

+ 0 - 7
FlatCAM.py

@@ -60,11 +60,4 @@ if __name__ == '__main__':
 
 
     fc = App()
     fc = App()
 
 
-    if settings.contains("maximized_gui"):
-        maximized_ui = settings.value('maximized_gui', type=bool)
-        if maximized_ui is True:
-            fc.ui.showMaximized()
-        else:
-            fc.ui.show()
-
     sys.exit(app.exec_())
     sys.exit(app.exec_())

+ 75 - 17
FlatCAMApp.py

@@ -80,10 +80,14 @@ class App(QtCore.QObject):
 
 
     # Get Cmd Line Options
     # Get Cmd Line Options
     cmd_line_shellfile = ''
     cmd_line_shellfile = ''
-    cmd_line_help = "FlatCam.py --shellfile=<cmd_line_shellfile>"
+    cmd_line_shellvar = ''
+
+    cmd_line_help = "FlatCam.py --shellfile=<cmd_line_shellfile>\nFlatCam.py --shellvar=<1,'C:\path',23>"
     try:
     try:
         # Multiprocessing pool will spawn additional processes with 'multiprocessing-fork' flag
         # Multiprocessing pool will spawn additional processes with 'multiprocessing-fork' flag
-        cmd_line_options, args = getopt.getopt(sys.argv[1:], "h:", ["shellfile=", "multiprocessing-fork="])
+        cmd_line_options, args = getopt.getopt(sys.argv[1:], "h:", ["shellfile=",
+                                                                    "shellvar=",
+                                                                    "multiprocessing-fork="])
     except getopt.GetoptError:
     except getopt.GetoptError:
         print(cmd_line_help)
         print(cmd_line_help)
         sys.exit(2)
         sys.exit(2)
@@ -93,6 +97,8 @@ class App(QtCore.QObject):
             sys.exit()
             sys.exit()
         elif opt == '--shellfile':
         elif opt == '--shellfile':
             cmd_line_shellfile = arg
             cmd_line_shellfile = arg
+        elif opt == '--shellvar':
+            cmd_line_shellvar = arg
 
 
     # ## Logging ###
     # ## Logging ###
     log = logging.getLogger('base')
     log = logging.getLogger('base')
@@ -1905,7 +1911,7 @@ class App(QtCore.QObject):
             self.on_excellon_options_button)
             self.on_excellon_options_button)
 
 
         # when there are arguments at application startup this get launched
         # when there are arguments at application startup this get launched
-        self.args_at_startup[list].connect(lambda: self.on_startup_args())
+        self.args_at_startup[list].connect(self.on_startup_args)
 
 
         # connect the 'Apply' buttons from the Preferences/File Associations
         # connect the 'Apply' buttons from the Preferences/File Associations
         self.ui.fa_defaults_form.fa_excellon_group.exc_list_btn.clicked.connect(
         self.ui.fa_defaults_form.fa_excellon_group.exc_list_btn.clicked.connect(
@@ -2386,13 +2392,53 @@ class App(QtCore.QObject):
         # ###############################################################################
         # ###############################################################################
         App.log.debug("END of constructor. Releasing control.")
         App.log.debug("END of constructor. Releasing control.")
 
 
+        # #####################################################################################
+        # ########################## SHOW GUI #################################################
+        # #####################################################################################
+
+        # finish the splash
+        self.splash.finish(self.ui)
+
+        settings = QSettings("Open Source", "FlatCAM")
+        if settings.contains("maximized_gui"):
+            maximized_ui = settings.value('maximized_gui', type=bool)
+            if maximized_ui is True:
+                self.ui.showMaximized()
+            else:
+                self.ui.show()
+
         # #####################################################################################
         # #####################################################################################
         # ########################## START-UP ARGUMENTS #######################################
         # ########################## START-UP ARGUMENTS #######################################
         # #####################################################################################
         # #####################################################################################
 
 
         # test if the program was started with a script as parameter
         # test if the program was started with a script as parameter
+        if self.cmd_line_shellvar:
+            try:
+                cnt = 0
+                command_tcl = 0
+                for i in self.cmd_line_shellvar.split(','):
+                    if i is not None:
+                        try:
+                            command_tcl = eval(i)
+                        except:
+                            command_tcl = i
+
+                    command_tcl_formatted = 'set shellvar_{nr} {cmd}'.format(cmd=str(command_tcl), nr=str(cnt))
+                    cnt += 1
+
+                    # if there are Windows paths then replace the path separator with a Unix like one
+                    if sys.platform == 'win32':
+                        command_tcl_formatted = command_tcl_formatted.replace('\\', '/')
+                    self.shell._sysShell.exec_command(command_tcl_formatted, no_echo=True)
+            except Exception as ext:
+                print("ERROR: ", ext)
+                sys.exit(2)
+
         if self.cmd_line_shellfile:
         if self.cmd_line_shellfile:
             try:
             try:
+                if self.ui.shell_dock.isHidden():
+                    self.ui.shell_dock.show()
+
                 with open(self.cmd_line_shellfile, "r") as myfile:
                 with open(self.cmd_line_shellfile, "r") as myfile:
                     if show_splash:
                     if show_splash:
                         self.splash.showMessage('%s: %ssec\n%s' % (
                         self.splash.showMessage('%s: %ssec\n%s' % (
@@ -2407,14 +2453,11 @@ class App(QtCore.QObject):
                 print("ERROR: ", ext)
                 print("ERROR: ", ext)
                 sys.exit(2)
                 sys.exit(2)
 
 
-        # accept some type file as command line parameter: FlatCAM project, FlatCAM preferences or scripts
-        # the path/file_name must be enclosed in quotes if it contain spaces
+            # accept some type file as command line parameter: FlatCAM project, FlatCAM preferences or scripts
+            # the path/file_name must be enclosed in quotes if it contain spaces
         if App.args:
         if App.args:
             self.args_at_startup.emit(App.args)
             self.args_at_startup.emit(App.args)
 
 
-        # finish the splash
-        self.splash.finish(self.ui)
-
     @staticmethod
     @staticmethod
     def copy_and_overwrite(from_path, to_path):
     def copy_and_overwrite(from_path, to_path):
         """
         """
@@ -2433,14 +2476,15 @@ class App(QtCore.QObject):
             from_new_path = os.path.dirname(os.path.realpath(__file__)) + '\\flatcamGUI\\VisPyData\\data'
             from_new_path = os.path.dirname(os.path.realpath(__file__)) + '\\flatcamGUI\\VisPyData\\data'
             shutil.copytree(from_new_path, to_path)
             shutil.copytree(from_new_path, to_path)
 
 
-    def on_startup_args(self, args=None):
+    def on_startup_args(self, args):
         """
         """
         This will process any arguments provided to the application at startup. Like trying to launch a file or project.
         This will process any arguments provided to the application at startup. Like trying to launch a file or project.
 
 
         :param args: a list containing the application args at startup
         :param args: a list containing the application args at startup
         :return: None
         :return: None
         """
         """
-        if args:
+
+        if args is not None:
             args_to_process = args
             args_to_process = args
         else:
         else:
             args_to_process = App.args
             args_to_process = App.args
@@ -2491,6 +2535,13 @@ class App(QtCore.QObject):
                 except Exception as e:
                 except Exception as e:
                     log.debug("Could not open FlatCAM Script file as App parameter due: %s" % str(e))
                     log.debug("Could not open FlatCAM Script file as App parameter due: %s" % str(e))
 
 
+            elif 'quit' in argument or 'exit' in argument:
+                log.debug("App.on_startup_args() --> Quit event.")
+                sys.exit()
+
+            elif 'save' in argument:
+                log.debug("App.on_startup_args() --> Save event. App Defaults saved.")
+                self.save_defaults()
             else:
             else:
                 exc_list = self.ui.fa_defaults_form.fa_excellon_group.exc_list_text.get_value().split(',')
                 exc_list = self.ui.fa_defaults_form.fa_excellon_group.exc_list_text.get_value().split(',')
                 proc_arg = argument.lower()
                 proc_arg = argument.lower()
@@ -3125,18 +3176,20 @@ class App(QtCore.QObject):
         self.display_tcl_error(text)
         self.display_tcl_error(text)
         raise self.TclErrorException(text)
         raise self.TclErrorException(text)
 
 
-    def exec_command(self, text, no_plot=None):
+    def exec_command(self, text, no_echo=False):
         """
         """
         Handles input from the shell. See FlatCAMApp.setup_shell for shell commands.
         Handles input from the shell. See FlatCAMApp.setup_shell for shell commands.
         Also handles execution in separated threads
         Also handles execution in separated threads
 
 
         :param text: FlatCAM TclCommand with parameters
         :param text: FlatCAM TclCommand with parameters
+        :param no_echo: If True it will not try to print to the Shell because most likely the shell is hidden and it
+        will create crashes of the _Expandable_Edit widget
         :return: output if there was any
         :return: output if there was any
         """
         """
 
 
         self.report_usage('exec_command')
         self.report_usage('exec_command')
 
 
-        result = self.exec_command_test(text, False)
+        result = self.exec_command_test(text, False, no_echo=no_echo)
 
 
         # MS: added this method call so the geometry is updated once the TCL command is executed
         # MS: added this method call so the geometry is updated once the TCL command is executed
         # if no_plot is None:
         # if no_plot is None:
@@ -3144,35 +3197,40 @@ class App(QtCore.QObject):
 
 
         return result
         return result
 
 
-    def exec_command_test(self, text, reraise=True):
+    def exec_command_test(self, text, reraise=True, no_echo=False):
         """
         """
         Same as exec_command(...) with additional control over  exceptions.
         Same as exec_command(...) with additional control over  exceptions.
         Handles input from the shell. See FlatCAMApp.setup_shell for shell commands.
         Handles input from the shell. See FlatCAMApp.setup_shell for shell commands.
 
 
         :param text: Input command
         :param text: Input command
         :param reraise: Re-raise TclError exceptions in Python (mostly for unitttests).
         :param reraise: Re-raise TclError exceptions in Python (mostly for unitttests).
+        :param no_echo: If True it will not try to print to the Shell because most likely the shell is hidden and it
+        will create crashes of the _Expandable_Edit widget
         :return: Output from the command
         :return: Output from the command
         """
         """
 
 
         tcl_command_string = str(text)
         tcl_command_string = str(text)
 
 
         try:
         try:
-            self.shell.open_proccessing()  # Disables input box.
+            if no_echo is False:
+                self.shell.open_proccessing()  # Disables input box.
 
 
             result = self.tcl.eval(str(tcl_command_string))
             result = self.tcl.eval(str(tcl_command_string))
-            if result != 'None':
+            if result != 'None' and no_echo is False:
                 self.shell.append_output(result + '\n')
                 self.shell.append_output(result + '\n')
 
 
         except tk.TclError as e:
         except tk.TclError as e:
             # This will display more precise answer if something in TCL shell fails
             # This will display more precise answer if something in TCL shell fails
             result = self.tcl.eval("set errorInfo")
             result = self.tcl.eval("set errorInfo")
             self.log.error("Exec command Exception: %s" % (result + '\n'))
             self.log.error("Exec command Exception: %s" % (result + '\n'))
-            self.shell.append_error('ERROR: ' + result + '\n')
+            if no_echo is False:
+                self.shell.append_error('ERROR: ' + result + '\n')
             # Show error in console and just return or in test raise exception
             # Show error in console and just return or in test raise exception
             if reraise:
             if reraise:
                 raise e
                 raise e
         finally:
         finally:
-            self.shell.close_proccessing()
+            if no_echo is False:
+                self.shell.close_proccessing()
             pass
             pass
         return result
         return result
 
 

+ 6 - 0
README.md

@@ -15,6 +15,12 @@ CAD program, and create G-Code for Isolation routing.
 - fixed issue #315 where a script run with the --shellfile argument crashed the program if it contained a TclCommand New
 - fixed issue #315 where a script run with the --shellfile argument crashed the program if it contained a TclCommand New
 - added messages in the Splash Screen when running FlatCAM with arguments at startup
 - added messages in the Splash Screen when running FlatCAM with arguments at startup
 - fixed issue #313 where TclCommand drillcncjob is spitting errors in Tcl Shell which should be ignored
 - fixed issue #313 where TclCommand drillcncjob is spitting errors in Tcl Shell which should be ignored
+- fixed an bug where the pywrapcp name from Google OR-Tools is not defined; fix issue #316
+- if FlatCAM is started with the 'quit' or 'exit' as argument it will close immediately and it will close also another instance of FlatCAM that may be running
+- added a new command line parameter for FlatCAM named '--shellvars' which can load a text file with variables for Tcl Shell in the format: one variable assignment per line and looking like: 'a=3' without quotes
+- made --shellvars into --shellvar and make it only one list of commands passed to the Tcl. The list is separated by comma but without spaces. The variables are accessed in Tcl with the names shellvar_x where x is the index in the list of command comma separated values
+- fixed an issue in the TclShell that generated an exception IndexError which crashed the software
+- fixed the --shellvar and --shellfile FlatCAM arguments to work together but the --shellvar has precedence over --shellfile as it is most likely that whatever variable set by --shellvar will be used in the script file run by --shellfile
 
 
 16.09.2019
 16.09.2019
 
 

+ 285 - 278
camlib.py

@@ -5868,313 +5868,320 @@ class CNCjob(Geometry):
         self.app.inform.emit('%s...' %
         self.app.inform.emit('%s...' %
                              _("Starting G-Code"))
                              _("Starting G-Code"))
 
 
-        if excellon_optimization_type == 'M':
-            log.debug("Using OR-Tools Metaheuristic Guided Local Search drill path optimization.")
-            if exobj.drills:
-                for tool in tools:
-                    self.tool=tool
-                    self.postdata['toolC'] = exobj.tools[tool]["C"]
-                    self.tooldia = exobj.tools[tool]["C"]
-
-                    if self.app.abort_flag:
-                        # graceful abort requested by the user
-                        raise FlatCAMApp.GracefulException
-
-                    # ###############################################
-                    # ############ Create the data. #################
-                    # ###############################################
-
-                    node_list = []
-                    locations = create_data_array()
-                    tsp_size = len(locations)
-                    num_routes = 1  # The number of routes, which is 1 in the TSP.
-                    # Nodes are indexed from 0 to tsp_size - 1. The depot is the starting node of the route.
-                    depot = 0
-                    # Create routing model.
-                    if tsp_size > 0:
-                        manager = pywrapcp.RoutingIndexManager(tsp_size, num_routes, depot)
-                        routing = pywrapcp.RoutingModel(manager)
-                        search_parameters = pywrapcp.DefaultRoutingSearchParameters()
-                        search_parameters.local_search_metaheuristic = (
-                            routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)
-
-                        # Set search time limit in milliseconds.
-                        if float(self.app.defaults["excellon_search_time"]) != 0:
-                            search_parameters.time_limit.seconds = int(
-                                float(self.app.defaults["excellon_search_time"]))
-                        else:
-                            search_parameters.time_limit.seconds = 3
-
-                        # Callback to the distance function. The callback takes two
-                        # arguments (the from and to node indices) and returns the distance between them.
-                        dist_between_locations = CreateDistanceCallback()
-                        dist_callback = dist_between_locations.Distance
-                        transit_callback_index = routing.RegisterTransitCallback(dist_callback)
-                        routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
-
-                        # Solve, returns a solution if any.
-                        assignment = routing.SolveWithParameters(search_parameters)
-
-                        if assignment:
-                            # Solution cost.
-                            log.info("Total distance: " + str(assignment.ObjectiveValue()))
-
-                            # Inspect solution.
-                            # Only one route here; otherwise iterate from 0 to routing.vehicles() - 1.
-                            route_number = 0
-                            node = routing.Start(route_number)
-                            start_node = node
-
-                            while not routing.IsEnd(node):
-                                if self.app.abort_flag:
-                                    # graceful abort requested by the user
-                                    raise FlatCAMApp.GracefulException
-
-                                node_list.append(node)
-                                node = assignment.Value(routing.NextVar(node))
-                        else:
-                            log.warning('No solution found.')
-                    else:
-                        log.warning('Specify an instance greater than 0.')
-                    # ############################################# ##
+        current_platform = platform.architecture()[0]
+        if current_platform == '64bit':
+            used_excellon_optimization_type = excellon_optimization_type
+            if used_excellon_optimization_type == 'M':
+                log.debug("Using OR-Tools Metaheuristic Guided Local Search drill path optimization.")
+                if exobj.drills:
+                    for tool in tools:
+                        self.tool=tool
+                        self.postdata['toolC'] = exobj.tools[tool]["C"]
+                        self.tooldia = exobj.tools[tool]["C"]
 
 
-                    # Only if tool has points.
-                    if tool in points:
                         if self.app.abort_flag:
                         if self.app.abort_flag:
                             # graceful abort requested by the user
                             # graceful abort requested by the user
                             raise FlatCAMApp.GracefulException
                             raise FlatCAMApp.GracefulException
 
 
-                        # Tool change sequence (optional)
-                        if toolchange:
-                            gcode += self.doformat(p.toolchange_code,toolchangexy=(self.oldx, self.oldy))
-                            gcode += self.doformat(p.spindle_code)  # Spindle start
-                            if self.dwell is True:
-                                gcode += self.doformat(p.dwell_code)  # Dwell time
-                        else:
-                            gcode += self.doformat(p.spindle_code)
-                            if self.dwell is True:
-                                gcode += self.doformat(p.dwell_code)  # Dwell time
-
-                        if self.units == 'MM':
-                            current_tooldia = float('%.2f' % float(exobj.tools[tool]["C"]))
+                        # ###############################################
+                        # ############ Create the data. #################
+                        # ###############################################
+
+                        node_list = []
+                        locations = create_data_array()
+                        tsp_size = len(locations)
+                        num_routes = 1  # The number of routes, which is 1 in the TSP.
+                        # Nodes are indexed from 0 to tsp_size - 1. The depot is the starting node of the route.
+                        depot = 0
+                        # Create routing model.
+                        if tsp_size > 0:
+                            manager = pywrapcp.RoutingIndexManager(tsp_size, num_routes, depot)
+                            routing = pywrapcp.RoutingModel(manager)
+                            search_parameters = pywrapcp.DefaultRoutingSearchParameters()
+                            search_parameters.local_search_metaheuristic = (
+                                routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)
+
+                            # Set search time limit in milliseconds.
+                            if float(self.app.defaults["excellon_search_time"]) != 0:
+                                search_parameters.time_limit.seconds = int(
+                                    float(self.app.defaults["excellon_search_time"]))
+                            else:
+                                search_parameters.time_limit.seconds = 3
+
+                            # Callback to the distance function. The callback takes two
+                            # arguments (the from and to node indices) and returns the distance between them.
+                            dist_between_locations = CreateDistanceCallback()
+                            dist_callback = dist_between_locations.Distance
+                            transit_callback_index = routing.RegisterTransitCallback(dist_callback)
+                            routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
+
+                            # Solve, returns a solution if any.
+                            assignment = routing.SolveWithParameters(search_parameters)
+
+                            if assignment:
+                                # Solution cost.
+                                log.info("Total distance: " + str(assignment.ObjectiveValue()))
+
+                                # Inspect solution.
+                                # Only one route here; otherwise iterate from 0 to routing.vehicles() - 1.
+                                route_number = 0
+                                node = routing.Start(route_number)
+                                start_node = node
+
+                                while not routing.IsEnd(node):
+                                    if self.app.abort_flag:
+                                        # graceful abort requested by the user
+                                        raise FlatCAMApp.GracefulException
+
+                                    node_list.append(node)
+                                    node = assignment.Value(routing.NextVar(node))
+                            else:
+                                log.warning('No solution found.')
                         else:
                         else:
-                            current_tooldia = float('%.4f' % float(exobj.tools[tool]["C"]))
-
-                        self.app.inform.emit(
-                            '%s: %s%s.' % (_("Starting G-Code for tool with diameter"),
-                                           str(current_tooldia),
-                                           str(self.units))
-                        )
-
-                        # TODO apply offset only when using the GUI, for TclCommand this will create an error
-                        # because the values for Z offset are created in build_ui()
-                        try:
-                            z_offset = float(self.tool_offset[current_tooldia]) * (-1)
-                        except KeyError:
-                            z_offset = 0
-                        self.z_cut += z_offset
-
-                        self.coordinates_type = self.app.defaults["cncjob_coords_type"]
-                        if self.coordinates_type == "G90":
-                            # Drillling! for Absolute coordinates type G90
-                            # variables to display the percentage of work done
-                            geo_len = len(node_list)
-                            disp_number = 0
-                            old_disp_number = 0
-                            log.warning("Number of drills for which to generate GCode: %s" % str(geo_len))
-
-                            loc_nr = 0
-                            for k in node_list:
-                                if self.app.abort_flag:
-                                    # graceful abort requested by the user
-                                    raise FlatCAMApp.GracefulException
-
-                                locx = locations[k][0]
-                                locy = locations[k][1]
-
-                                gcode += self.doformat(p.rapid_code, x=locx, y=locy)
-                                gcode += self.doformat(p.down_code, x=locx, y=locy)
+                            log.warning('Specify an instance greater than 0.')
+                        # ############################################# ##
+
+                        # Only if tool has points.
+                        if tool in points:
+                            if self.app.abort_flag:
+                                # graceful abort requested by the user
+                                raise FlatCAMApp.GracefulException
+
+                            # Tool change sequence (optional)
+                            if toolchange:
+                                gcode += self.doformat(p.toolchange_code,toolchangexy=(self.oldx, self.oldy))
+                                gcode += self.doformat(p.spindle_code)  # Spindle start
+                                if self.dwell is True:
+                                    gcode += self.doformat(p.dwell_code)  # Dwell time
+                            else:
+                                gcode += self.doformat(p.spindle_code)
+                                if self.dwell is True:
+                                    gcode += self.doformat(p.dwell_code)  # Dwell time
 
 
-                                measured_down_distance += abs(self.z_cut) + abs(self.z_move)
+                            if self.units == 'MM':
+                                current_tooldia = float('%.2f' % float(exobj.tools[tool]["C"]))
+                            else:
+                                current_tooldia = float('%.4f' % float(exobj.tools[tool]["C"]))
 
 
-                                if self.f_retract is False:
-                                    gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
-                                    measured_up_to_zero_distance += abs(self.z_cut)
-                                    measured_lift_distance += abs(self.z_move)
-                                else:
-                                    measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
+                            self.app.inform.emit(
+                                '%s: %s%s.' % (_("Starting G-Code for tool with diameter"),
+                                               str(current_tooldia),
+                                               str(self.units))
+                            )
 
 
-                                gcode += self.doformat(p.lift_code, x=locx, y=locy)
-                                measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
-                                self.oldx = locx
-                                self.oldy = locy
+                            # TODO apply offset only when using the GUI, for TclCommand this will create an error
+                            # because the values for Z offset are created in build_ui()
+                            try:
+                                z_offset = float(self.tool_offset[current_tooldia]) * (-1)
+                            except KeyError:
+                                z_offset = 0
+                            self.z_cut += z_offset
+
+                            self.coordinates_type = self.app.defaults["cncjob_coords_type"]
+                            if self.coordinates_type == "G90":
+                                # Drillling! for Absolute coordinates type G90
+                                # variables to display the percentage of work done
+                                geo_len = len(node_list)
+                                disp_number = 0
+                                old_disp_number = 0
+                                log.warning("Number of drills for which to generate GCode: %s" % str(geo_len))
+
+                                loc_nr = 0
+                                for k in node_list:
+                                    if self.app.abort_flag:
+                                        # graceful abort requested by the user
+                                        raise FlatCAMApp.GracefulException
+
+                                    locx = locations[k][0]
+                                    locy = locations[k][1]
+
+                                    gcode += self.doformat(p.rapid_code, x=locx, y=locy)
+                                    gcode += self.doformat(p.down_code, x=locx, y=locy)
+
+                                    measured_down_distance += abs(self.z_cut) + abs(self.z_move)
+
+                                    if self.f_retract is False:
+                                        gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
+                                        measured_up_to_zero_distance += abs(self.z_cut)
+                                        measured_lift_distance += abs(self.z_move)
+                                    else:
+                                        measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
 
 
-                                loc_nr += 1
-                                disp_number = int(np.interp(loc_nr, [0, geo_len], [0, 100]))
+                                    gcode += self.doformat(p.lift_code, x=locx, y=locy)
+                                    measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
+                                    self.oldx = locx
+                                    self.oldy = locy
 
 
-                                if old_disp_number < disp_number <= 100:
-                                    self.app.proc_container.update_view_text(' %d%%' % disp_number)
-                                    old_disp_number = disp_number
+                                    loc_nr += 1
+                                    disp_number = int(np.interp(loc_nr, [0, geo_len], [0, 100]))
 
 
-                        else:
-                            self.app.inform.emit('[ERROR_NOTCL] %s...' %
-                                                 _('G91 coordinates not implemented'))
-                            return 'fail'
-            else:
-                log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
-                          "The loaded Excellon file has no drills ...")
-                self.app.inform.emit('[ERROR_NOTCL] %s...' %
-                                     _('The loaded Excellon file has no drills'))
-                return 'fail'
+                                    if old_disp_number < disp_number <= 100:
+                                        self.app.proc_container.update_view_text(' %d%%' % disp_number)
+                                        old_disp_number = disp_number
 
 
-            log.debug("The total travel distance with OR-TOOLS Metaheuristics is: %s" % str(measured_distance))
-        elif excellon_optimization_type == 'B':
-            log.debug("Using OR-Tools Basic drill path optimization.")
-            if exobj.drills:
-                for tool in tools:
-                    if self.app.abort_flag:
-                        # graceful abort requested by the user
-                        raise FlatCAMApp.GracefulException
-
-                    self.tool=tool
-                    self.postdata['toolC']=exobj.tools[tool]["C"]
-                    self.tooldia = exobj.tools[tool]["C"]
+                            else:
+                                self.app.inform.emit('[ERROR_NOTCL] %s...' %
+                                                     _('G91 coordinates not implemented'))
+                                return 'fail'
+                else:
+                    log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
+                              "The loaded Excellon file has no drills ...")
+                    self.app.inform.emit('[ERROR_NOTCL] %s...' %
+                                         _('The loaded Excellon file has no drills'))
+                    return 'fail'
 
 
-                    # ############################################# ##
-                    node_list = []
-                    locations = create_data_array()
-                    tsp_size = len(locations)
-                    num_routes = 1  # The number of routes, which is 1 in the TSP.
-
-                    # Nodes are indexed from 0 to tsp_size - 1. The depot is the starting node of the route.
-                    depot = 0
-
-                    # Create routing model.
-                    if tsp_size > 0:
-                        manager = pywrapcp.RoutingIndexManager(tsp_size, num_routes, depot)
-                        routing = pywrapcp.RoutingModel(manager)
-                        search_parameters = pywrapcp.DefaultRoutingSearchParameters()
-
-                        # Callback to the distance function. The callback takes two
-                        # arguments (the from and to node indices) and returns the distance between them.
-                        dist_between_locations = CreateDistanceCallback()
-                        dist_callback = dist_between_locations.Distance
-                        transit_callback_index = routing.RegisterTransitCallback(dist_callback)
-                        routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
-
-                        # Solve, returns a solution if any.
-                        assignment = routing.SolveWithParameters(search_parameters)
-
-                        if assignment:
-                            # Solution cost.
-                            log.info("Total distance: " + str(assignment.ObjectiveValue()))
-
-                            # Inspect solution.
-                            # Only one route here; otherwise iterate from 0 to routing.vehicles() - 1.
-                            route_number = 0
-                            node = routing.Start(route_number)
-                            start_node = node
-
-                            while not routing.IsEnd(node):
-                                node_list.append(node)
-                                node = assignment.Value(routing.NextVar(node))
-                        else:
-                            log.warning('No solution found.')
-                    else:
-                        log.warning('Specify an instance greater than 0.')
-                    # ############################################# ##
+                log.debug("The total travel distance with OR-TOOLS Metaheuristics is: %s" % str(measured_distance))
 
 
-                    # Only if tool has points.
-                    if tool in points:
+            if used_excellon_optimization_type == 'B':
+                log.debug("Using OR-Tools Basic drill path optimization.")
+                if exobj.drills:
+                    for tool in tools:
                         if self.app.abort_flag:
                         if self.app.abort_flag:
                             # graceful abort requested by the user
                             # graceful abort requested by the user
                             raise FlatCAMApp.GracefulException
                             raise FlatCAMApp.GracefulException
 
 
-                        # Tool change sequence (optional)
-                        if toolchange:
-                            gcode += self.doformat(p.toolchange_code,toolchangexy=(self.oldx, self.oldy))
-                            gcode += self.doformat(p.spindle_code)  # Spindle start)
-                            if self.dwell is True:
-                                gcode += self.doformat(p.dwell_code)  # Dwell time
-                        else:
-                            gcode += self.doformat(p.spindle_code)
-                            if self.dwell is True:
-                                gcode += self.doformat(p.dwell_code)  # Dwell time
-
-                        if self.units == 'MM':
-                            current_tooldia = float('%.2f' % float(exobj.tools[tool]["C"]))
+                        self.tool=tool
+                        self.postdata['toolC']=exobj.tools[tool]["C"]
+                        self.tooldia = exobj.tools[tool]["C"]
+
+                        # ############################################# ##
+                        node_list = []
+                        locations = create_data_array()
+                        tsp_size = len(locations)
+                        num_routes = 1  # The number of routes, which is 1 in the TSP.
+
+                        # Nodes are indexed from 0 to tsp_size - 1. The depot is the starting node of the route.
+                        depot = 0
+
+                        # Create routing model.
+                        if tsp_size > 0:
+                            manager = pywrapcp.RoutingIndexManager(tsp_size, num_routes, depot)
+                            routing = pywrapcp.RoutingModel(manager)
+                            search_parameters = pywrapcp.DefaultRoutingSearchParameters()
+
+                            # Callback to the distance function. The callback takes two
+                            # arguments (the from and to node indices) and returns the distance between them.
+                            dist_between_locations = CreateDistanceCallback()
+                            dist_callback = dist_between_locations.Distance
+                            transit_callback_index = routing.RegisterTransitCallback(dist_callback)
+                            routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
+
+                            # Solve, returns a solution if any.
+                            assignment = routing.SolveWithParameters(search_parameters)
+
+                            if assignment:
+                                # Solution cost.
+                                log.info("Total distance: " + str(assignment.ObjectiveValue()))
+
+                                # Inspect solution.
+                                # Only one route here; otherwise iterate from 0 to routing.vehicles() - 1.
+                                route_number = 0
+                                node = routing.Start(route_number)
+                                start_node = node
+
+                                while not routing.IsEnd(node):
+                                    node_list.append(node)
+                                    node = assignment.Value(routing.NextVar(node))
+                            else:
+                                log.warning('No solution found.')
                         else:
                         else:
-                            current_tooldia = float('%.4f' % float(exobj.tools[tool]["C"]))
-
-                        self.app.inform.emit(
-                            '%s: %s%s.' % (_("Starting G-Code for tool with diameter"),
-                                           str(current_tooldia),
-                                           str(self.units))
-                        )
-
-                        # TODO apply offset only when using the GUI, for TclCommand this will create an error
-                        # because the values for Z offset are created in build_ui()
-                        try:
-                            z_offset = float(self.tool_offset[current_tooldia]) * (-1)
-                        except KeyError:
-                            z_offset = 0
-                        self.z_cut += z_offset
-
-                        self.coordinates_type = self.app.defaults["cncjob_coords_type"]
-                        if self.coordinates_type == "G90":
-                            # Drillling! for Absolute coordinates type G90
-                            # variables to display the percentage of work done
-                            geo_len = len(node_list)
-                            disp_number = 0
-                            old_disp_number = 0
-                            log.warning("Number of drills for which to generate GCode: %s" % str(geo_len))
-
-                            loc_nr = 0
-                            for k in node_list:
-                                if self.app.abort_flag:
-                                    # graceful abort requested by the user
-                                    raise FlatCAMApp.GracefulException
-
-                                locx = locations[k][0]
-                                locy = locations[k][1]
+                            log.warning('Specify an instance greater than 0.')
+                        # ############################################# ##
+
+                        # Only if tool has points.
+                        if tool in points:
+                            if self.app.abort_flag:
+                                # graceful abort requested by the user
+                                raise FlatCAMApp.GracefulException
+
+                            # Tool change sequence (optional)
+                            if toolchange:
+                                gcode += self.doformat(p.toolchange_code,toolchangexy=(self.oldx, self.oldy))
+                                gcode += self.doformat(p.spindle_code)  # Spindle start)
+                                if self.dwell is True:
+                                    gcode += self.doformat(p.dwell_code)  # Dwell time
+                            else:
+                                gcode += self.doformat(p.spindle_code)
+                                if self.dwell is True:
+                                    gcode += self.doformat(p.dwell_code)  # Dwell time
 
 
-                                gcode += self.doformat(p.rapid_code, x=locx, y=locy)
-                                gcode += self.doformat(p.down_code, x=locx, y=locy)
+                            if self.units == 'MM':
+                                current_tooldia = float('%.2f' % float(exobj.tools[tool]["C"]))
+                            else:
+                                current_tooldia = float('%.4f' % float(exobj.tools[tool]["C"]))
 
 
-                                measured_down_distance += abs(self.z_cut) + abs(self.z_move)
+                            self.app.inform.emit(
+                                '%s: %s%s.' % (_("Starting G-Code for tool with diameter"),
+                                               str(current_tooldia),
+                                               str(self.units))
+                            )
 
 
-                                if self.f_retract is False:
-                                    gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
-                                    measured_up_to_zero_distance += abs(self.z_cut)
-                                    measured_lift_distance += abs(self.z_move)
-                                else:
-                                    measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
+                            # TODO apply offset only when using the GUI, for TclCommand this will create an error
+                            # because the values for Z offset are created in build_ui()
+                            try:
+                                z_offset = float(self.tool_offset[current_tooldia]) * (-1)
+                            except KeyError:
+                                z_offset = 0
+                            self.z_cut += z_offset
+
+                            self.coordinates_type = self.app.defaults["cncjob_coords_type"]
+                            if self.coordinates_type == "G90":
+                                # Drillling! for Absolute coordinates type G90
+                                # variables to display the percentage of work done
+                                geo_len = len(node_list)
+                                disp_number = 0
+                                old_disp_number = 0
+                                log.warning("Number of drills for which to generate GCode: %s" % str(geo_len))
+
+                                loc_nr = 0
+                                for k in node_list:
+                                    if self.app.abort_flag:
+                                        # graceful abort requested by the user
+                                        raise FlatCAMApp.GracefulException
+
+                                    locx = locations[k][0]
+                                    locy = locations[k][1]
+
+                                    gcode += self.doformat(p.rapid_code, x=locx, y=locy)
+                                    gcode += self.doformat(p.down_code, x=locx, y=locy)
+
+                                    measured_down_distance += abs(self.z_cut) + abs(self.z_move)
+
+                                    if self.f_retract is False:
+                                        gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
+                                        measured_up_to_zero_distance += abs(self.z_cut)
+                                        measured_lift_distance += abs(self.z_move)
+                                    else:
+                                        measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
 
 
-                                gcode += self.doformat(p.lift_code, x=locx, y=locy)
-                                measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
-                                self.oldx = locx
-                                self.oldy = locy
+                                    gcode += self.doformat(p.lift_code, x=locx, y=locy)
+                                    measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
+                                    self.oldx = locx
+                                    self.oldy = locy
 
 
-                                loc_nr += 1
-                                disp_number = int(np.interp(loc_nr, [0, geo_len], [0, 100]))
+                                    loc_nr += 1
+                                    disp_number = int(np.interp(loc_nr, [0, geo_len], [0, 100]))
 
 
-                                if old_disp_number < disp_number <= 100:
-                                    self.app.proc_container.update_view_text(' %d%%' % disp_number)
-                                    old_disp_number = disp_number
+                                    if old_disp_number < disp_number <= 100:
+                                        self.app.proc_container.update_view_text(' %d%%' % disp_number)
+                                        old_disp_number = disp_number
 
 
-                        else:
-                            self.app.inform.emit('[ERROR_NOTCL] %s...' %
-                                                 _('G91 coordinates not implemented'))
-                            return 'fail'
-            else:
-                log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
-                          "The loaded Excellon file has no drills ...")
-                self.app.inform.emit('[ERROR_NOTCL] %s...' %
-                                     _('The loaded Excellon file has no drills'))
-                return 'fail'
+                            else:
+                                self.app.inform.emit('[ERROR_NOTCL] %s...' %
+                                                     _('G91 coordinates not implemented'))
+                                return 'fail'
+                else:
+                    log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
+                              "The loaded Excellon file has no drills ...")
+                    self.app.inform.emit('[ERROR_NOTCL] %s...' %
+                                         _('The loaded Excellon file has no drills'))
+                    return 'fail'
 
 
-            log.debug("The total travel distance with OR-TOOLS Basic Algorithm is: %s" % str(measured_distance))
+                log.debug("The total travel distance with OR-TOOLS Basic Algorithm is: %s" % str(measured_distance))
         else:
         else:
+            used_excellon_optimization_type = 'T'
+
+        if used_excellon_optimization_type == 'T':
             log.debug("Using Travelling Salesman drill path optimization.")
             log.debug("Using Travelling Salesman drill path optimization.")
             for tool in tools:
             for tool in tools:
                 if self.app.abort_flag:
                 if self.app.abort_flag:

+ 1 - 0
config/configuration.txt

@@ -1 +1,2 @@
 portable=False
 portable=False
+headless=False

+ 7 - 4
flatcamTools/ToolShell.py

@@ -142,10 +142,13 @@ class TermWidget(QWidget):
         self._append_to_browser('in', '> ' + text + '\n')
         self._append_to_browser('in', '> ' + text + '\n')
 
 
         if len(self._history) < 2 or self._history[-2] != text:  # don't insert duplicating items
         if len(self._history) < 2 or self._history[-2] != text:  # don't insert duplicating items
-            if text[-1] == '\n':
-                self._history.insert(-1, text[:-1])
-            else:
-                self._history.insert(-1, text)
+            try:
+                if text[-1] == '\n':
+                    self._history.insert(-1, text[:-1])
+                else:
+                    self._history.insert(-1, text)
+            except IndexError:
+                return
 
 
         self._historyIndex = len(self._history) - 1
         self._historyIndex = len(self._history) - 1
 
 

BIN
locale/pt_BR/LC_MESSAGES/strings.mo


Разница между файлами не показана из-за своего большого размера
+ 245 - 220
locale/pt_BR/LC_MESSAGES/strings.po


Некоторые файлы не были показаны из-за большого количества измененных файлов