Sfoglia il codice sorgente

Merged in marius_stanciu/flatcam_beta/Beta (pull request #288)

Beta - first push on year 2020
Marius Stanciu 6 anni fa
parent
commit
b4076b1e12

+ 33 - 66
FlatCAMApp.py

@@ -20,7 +20,6 @@ import shutil
 import stat
 
 from stat import S_IREAD, S_IRGRP, S_IROTH
-import subprocess
 import ctypes
 
 # import tkinter as tk
@@ -39,7 +38,7 @@ import gc
 from xml.dom.minidom import parseString as parse_xml_string
 
 from multiprocessing.connection import Listener, Client
-from multiprocessing import Pool, cpu_count
+from multiprocessing import Pool
 import socket
 from array import array
 
@@ -241,6 +240,9 @@ class App(QtCore.QObject):
     # signal emitted when jumping
     jump_signal = pyqtSignal(tuple)
 
+    # close app signal
+    close_app_signal = pyqtSignal()
+
     def __init__(self, user_defaults=True):
         """
         Starts the application.
@@ -2011,8 +2013,6 @@ class App(QtCore.QObject):
         self.ui.pref_close_button.clicked.connect(self.on_pref_close_button)
 
         self.ui.pref_defaults_button.clicked.connect(self.on_restore_defaults_preferences)
-        self.ui.pref_open_button.clicked.connect(self.on_preferences_open_folder)
-        self.ui.clear_btn.clicked.connect(self.on_gui_clear)
 
         # #############################################################################
         # ######################### GUI PREFERENCES SIGNALS ###########################
@@ -2136,6 +2136,8 @@ class App(QtCore.QObject):
 
         self.ui.grid_snap_btn.triggered.connect(self.on_grid_snap_triggered)
 
+        # signal to close the application
+        self.close_app_signal.connect(self.kill_app)
         # #####################################################################################
         # ########### FINISHED CONNECTING SIGNALS #############################################
         # #####################################################################################
@@ -2695,20 +2697,24 @@ class App(QtCore.QObject):
                 sys.exit(2)
 
         if self.cmd_line_shellfile:
-            try:
+            if self.cmd_line_headless != 1:
                 if self.ui.shell_dock.isHidden():
                     self.ui.shell_dock.show()
-
+            try:
                 with open(self.cmd_line_shellfile, "r") as myfile:
-                    if show_splash:
-                        self.splash.showMessage('%s: %ssec\n%s' % (
-                            _("Canvas initialization started.\n"
-                              "Canvas initialization finished in"), '%.2f' % self.used_time,
-                            _("Executing Tcl Script ...")),
-                                                alignment=Qt.AlignBottom | Qt.AlignLeft,
-                                                color=QtGui.QColor("gray"))
+                    # if show_splash:
+                    #     self.splash.showMessage('%s: %ssec\n%s' % (
+                    #         _("Canvas initialization started.\n"
+                    #           "Canvas initialization finished in"), '%.2f' % self.used_time,
+                    #         _("Executing Tcl Script ...")),
+                    #                             alignment=Qt.AlignBottom | Qt.AlignLeft,
+                    #                             color=QtGui.QColor("gray"))
                     cmd_line_shellfile_text = myfile.read()
-                    self.shell._sysShell.exec_command(cmd_line_shellfile_text)
+                    if self.cmd_line_headless != 1:
+                        self.shell._sysShell.exec_command(cmd_line_shellfile_text)
+                    else:
+                        self.shell._sysShell.exec_command(cmd_line_shellfile_text, no_echo=True)
+
             except Exception as ext:
                 print("ERROR: ", ext)
                 sys.exit(2)
@@ -3606,7 +3612,7 @@ class App(QtCore.QObject):
 
         try:
             if no_echo is False:
-                self.shell.open_proccessing()  # Disables input box.
+                self.shell.open_processing()  # Disables input box.
 
             result = self.tcl.eval(str(tcl_command_string))
             if result != 'None' and no_echo is False:
@@ -3624,7 +3630,7 @@ class App(QtCore.QObject):
                 raise e
         finally:
             if no_echo is False:
-                self.shell.close_proccessing()
+                self.shell.close_processing()
             pass
         return result
 
@@ -3978,58 +3984,13 @@ class App(QtCore.QObject):
                 json.dump(defaults_from_file, f, default=to_dict, indent=2, sort_keys=True)
                 f.close()
             except Exception:
-                self.inform.emit('[ERROR_NOTCL] %s' % _("Failed to write defaults to file."))
+                self.inform.emit('[ERROR_NOTCL] %s %s' % (_("Failed to write defaults to file."), str(filename)))
                 return
         if self.defaults["global_open_style"] is False:
             self.file_opened.emit("preferences", filename)
         self.file_saved.emit("preferences", filename)
         self.inform.emit('[success] %s: %s' % (_("Exported preferences to"), filename))
 
-    def on_preferences_open_folder(self):
-        """
-        Will open an Explorer window set to the folder path where the FlatCAM preferences files are usually saved.
-
-        :return: None
-        """
-        self.report_usage("on_preferences_open_folder()")
-
-        if sys.platform == 'win32':
-            subprocess.Popen('explorer %s' % self.data_path)
-        elif sys.platform == 'darwin':
-            os.system('open "%s"' % self.data_path)
-        else:
-            subprocess.Popen(['xdg-open', self.data_path])
-        self.inform.emit('[success] %s' %
-                         _("FlatCAM Preferences Folder opened."))
-
-    def on_gui_clear(self):
-        theme_settings = QtCore.QSettings("Open Source", "FlatCAM")
-        theme_settings.setValue('theme', 'white')
-
-        del theme_settings
-
-        resource_loc = 'share'
-
-        msgbox = QtWidgets.QMessageBox()
-        msgbox.setText(_("Are you sure you want to delete the GUI Settings? "
-                         "\n")
-                       )
-        msgbox.setWindowTitle(_("Clear GUI Settings"))
-        msgbox.setWindowIcon(QtGui.QIcon(resource_loc + '/trash32.png'))
-        bt_yes = msgbox.addButton(_('Yes'), QtWidgets.QMessageBox.YesRole)
-        bt_no = msgbox.addButton(_('No'), QtWidgets.QMessageBox.NoRole)
-
-        msgbox.setDefaultButton(bt_no)
-        msgbox.exec_()
-        response = msgbox.clickedButton()
-
-        if response == bt_yes:
-            settings = QSettings("Open Source", "FlatCAM")
-            for key in settings.allKeys():
-                settings.remove(key)
-            # This will write the setting to the platform specific storage.
-            del settings
-
     def save_geometry(self, x, y, width, height, notebook_width):
         """
         Will save the application geometry and positions in the defaults discitionary to be restored at the next
@@ -4981,13 +4942,14 @@ class App(QtCore.QObject):
             self.defaults["global_toolbar_view"] = tb_status
 
         # Save update options
+        filename = data_path + "/current_defaults.FlatConfig"
         try:
-            f = open(data_path + "/current_defaults.FlatConfig", "w")
+            f = open(filename, "w")
             json.dump(defaults, f, default=to_dict, indent=2, sort_keys=True)
             f.close()
         except Exception as e:
             log.debug("App.save_defaults() --> %s" % str(e))
-            self.inform.emit('[ERROR_NOTCL] %s' % _("Failed to write defaults to file."))
+            self.inform.emit('[ERROR_NOTCL] %s %s' % (_("Failed to write defaults to file."), str(filename)))
             return
 
         if not silent:
@@ -5138,7 +5100,13 @@ class App(QtCore.QObject):
             del stgs
 
         log.debug("App.final_save() --> App UI state saved.")
+        self.close_app_signal.emit()
+
+    def kill_app(self):
         QtWidgets.qApp.quit()
+        # When the main event loop is not started yet in which case the qApp.quit() will do nothing
+        # we use the following command
+        sys.exit(0)
 
     def on_portable_checked(self, state):
         """
@@ -10043,8 +10011,7 @@ class App(QtCore.QObject):
 
         if filename == "":
             if silent is False:
-                self.inform.emit('[WARNING_NOTCL] %s' %
-                                 _("Run TCL script cancelled."))
+                self.inform.emit('[WARNING_NOTCL] %s' % _("Run TCL script cancelled."))
         else:
             if self.cmd_line_headless != 1:
                 if self.ui.shell_dock.isHidden():

+ 2 - 2
FlatCAMObj.py

@@ -7252,7 +7252,7 @@ class FlatCAMScript(FlatCAMObj):
 
                 # execute the actual Tcl command
                 try:
-                    self.app.shell.open_proccessing()  # Disables input box.
+                    self.app.shell.open_processing()  # Disables input box.
 
                     result = self.app.tcl.eval(str(new_command))
                     if result != 'None':
@@ -7270,7 +7270,7 @@ class FlatCAMScript(FlatCAMObj):
             log.error("Exec command Exception: %s" % (result + '\n'))
             self.app.shell.append_error('ERROR: ' + result + '\n')
 
-        self.app.shell.close_proccessing()
+        self.app.shell.close_processing()
 
     def on_autocomplete_changed(self, state):
         if state:

+ 7 - 0
README.md

@@ -9,6 +9,13 @@ CAD program, and create G-Code for Isolation routing.
 
 =================================================
 
+1.01.2020
+
+- fixed bug in NCC Tool: after trying to add a tool already in the Tool Table when trying to change the Tool Type the GUI does not change
+- final fix for app not quiting when running a script as argument, script that has the quit_flatcam Tcl command; fixed issue #360
+- fixed issue #363. The Tcl command drillcncjob does not create tool cut, does not allow creation of gcode, it forces the usage of dwell and dwelltime parameters
+
+
 30.12.2019
 
 - Buffer sub-tool in Transform Tool: added the possibility to apply a factor effectively scaling the aperture size thus the copper features sizes

+ 0 - 1
camlib.py

@@ -2550,7 +2550,6 @@ class CNCjob(Geometry):
                     self.exc_cnc_tools[it[1]]['nr_slots'] = slot_no
                     self.exc_cnc_tools[it[1]]['offset_z'] = z_off
                     self.exc_cnc_tools[it[1]]['data'] = default_data
-
                     self.exc_cnc_tools[it[1]]['solid_geometry'] = deepcopy(sol_geo)
 
         self.app.inform.emit(_("Creating a list of points to drill..."))

+ 47 - 0
flatcamGUI/FlatCAMGUI.py

@@ -18,6 +18,9 @@ from matplotlib.backend_bases import KeyEvent as mpl_key_event
 import webbrowser
 from copy import deepcopy
 from datetime import datetime
+
+import subprocess
+import os
 import gettext
 import FlatCAMTranslation as fcTranslate
 import builtins
@@ -2340,6 +2343,9 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
         self.lock_toolbar(lock=lock_state)
         self.lock_action.triggered[bool].connect(self.lock_toolbar)
 
+        self.pref_open_button.clicked.connect(self.on_preferences_open_folder)
+        self.clear_btn.clicked.connect(self.on_gui_clear)
+
         # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
         # %%%%%%%%%%%%%%%%% GUI Building FINISHED %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
         # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2360,6 +2366,47 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
 
         return False
 
+    def on_preferences_open_folder(self):
+        """
+        Will open an Explorer window set to the folder path where the FlatCAM preferences files are usually saved.
+
+        :return: None
+        """
+
+        if sys.platform == 'win32':
+            subprocess.Popen('explorer %s' % self.app.data_path)
+        elif sys.platform == 'darwin':
+            os.system('open "%s"' % self.app.data_path)
+        else:
+            subprocess.Popen(['xdg-open', self.app.data_path])
+        self.app.inform.emit('[success] %s' % _("FlatCAM Preferences Folder opened."))
+
+    def on_gui_clear(self):
+        theme_settings = QtCore.QSettings("Open Source", "FlatCAM")
+        theme_settings.setValue('theme', 'white')
+
+        del theme_settings
+
+        resource_loc = self.app.resource_location
+
+        msgbox = QtWidgets.QMessageBox()
+        msgbox.setText(_("Are you sure you want to delete the GUI Settings? \n"))
+        msgbox.setWindowTitle(_("Clear GUI Settings"))
+        msgbox.setWindowIcon(QtGui.QIcon(resource_loc + '/trash32.png'))
+        bt_yes = msgbox.addButton(_('Yes'), QtWidgets.QMessageBox.YesRole)
+        bt_no = msgbox.addButton(_('No'), QtWidgets.QMessageBox.NoRole)
+
+        msgbox.setDefaultButton(bt_no)
+        msgbox.exec_()
+        response = msgbox.clickedButton()
+
+        if response == bt_yes:
+            settings = QSettings("Open Source", "FlatCAM")
+            for key in settings.allKeys():
+                settings.remove(key)
+            # This will write the setting to the platform specific storage.
+            del settings
+
     def populate_toolbars(self):
         """
         Will populate the App Toolbars with theie actions

+ 2 - 1
flatcamTools/ToolNonCopperClear.py

@@ -1007,7 +1007,8 @@ class NonCopperClear(FlatCAMTool, Gerber):
         if float('%.*f' % (self.decimals, tool_dia)) in tool_dias:
             if muted is None:
                 self.app.inform.emit('[WARNING_NOTCL] %s' % _("Adding tool cancelled. Tool already in Tool Table."))
-            self.tools_table.itemChanged.connect(self.on_tool_edit)
+            # self.tools_table.itemChanged.connect(self.on_tool_edit)
+            self.ui_connect()
             return
         else:
             if muted is None:

+ 1 - 1
flatcamTools/ToolProperties.py

@@ -468,7 +468,7 @@ class Properties(FlatCAMTool):
                         _("Depth of Cut"),
                         '%.*f %s' % (
                             self.decimals,
-                            (obj.z_cut - obj.tool_offset[tool_dia]),
+                            (obj.z_cut - abs(obj.tool_offset[tool_dia])),
                             self.app.defaults['units'].lower()
                         )
                     ],

+ 4 - 4
flatcamTools/ToolShell.py

@@ -56,7 +56,7 @@ class TermWidget(QWidget):
         self._history = ['']  # current empty line
         self._historyIndex = 0
 
-    def open_proccessing(self, detail=None):
+    def open_processing(self, detail=None):
         """
         Open processing and disable using shell commands again until all commands are finished
 
@@ -67,14 +67,14 @@ class TermWidget(QWidget):
         self._edit.setTextColor(Qt.white)
         self._edit.setTextBackgroundColor(Qt.darkGreen)
         if detail is None:
-            self._edit.setPlainText(_("...proccessing..."))
+            self._edit.setPlainText(_("...processing..."))
         else:
-            self._edit.setPlainText('%s [%s]' % (_("...proccessing..."),  detail))
+            self._edit.setPlainText('%s [%s]' % (_("...processing..."),  detail))
 
         self._edit.setDisabled(True)
         self._edit.setFocus()
 
-    def close_proccessing(self):
+    def close_processing(self):
         """
         Close processing and enable using shell commands  again
         :return:

+ 3 - 3
tclCommands/TclCommand.py

@@ -258,8 +258,8 @@ class TclCommand(object):
         :return: raise exception
         """
 
-        # becouse of signaling we cannot call error to TCL from here but when task
-        # is finished also nonsignaled are handled here to better exception
+        # because of signaling we cannot call error to TCL from here but when task
+        # is finished also non-signaled are handled here to better exception
         # handling and  displayed after command is finished
         raise self.app.TclErrorException(text)
 
@@ -400,7 +400,7 @@ class TclCommandSignaled(TclCommand):
                 passed_timeout = self.app.defaults['global_background_timeout']
 
             # set detail for processing, it will be there until next open or close
-            self.app.shell.open_proccessing(self.get_current_command())
+            self.app.shell.open_processing(self.get_current_command())
 
             def handle_finished(obj):
                 self.app.shell_command_finished.disconnect(handle_finished)

+ 17 - 2
tclCommands/TclCommandDrillcncjob.py

@@ -48,7 +48,7 @@ class TclCommandDrillcncjob(TclCommandSignaled):
         'args': collections.OrderedDict([
             ('name', 'Name of the source object.'),
             ('drilled_dias',
-             'Comma separated tool diameters of the drills to be drilled (example: 0.6, 1.0 or 3.125).'),
+             'Comma separated tool diameters of the drills to be drilled (example: 0.6,1.0 or 3.125). No space allowed'),
             ('drillz', 'Drill depth into material (example: -2.0).'),
             ('travelz', 'Travel distance above material (example: 2.0).'),
             ('feedrate', 'Drilling feed rate.'),
@@ -74,7 +74,7 @@ class TclCommandDrillcncjob(TclCommandSignaled):
         ]),
         'examples': ['drillcncjob test.TXT -drillz -1.5 -travelz 14 -feedrate 222 -feedrate_rapid 456 -spindlespeed 777'
                      ' -toolchange True -toolchangez 33 -endz 22 -pp default\n'
-                     'Usage of -feedrate_rapid matter only when the posptocessor is using it, like -marlin-.']
+                     'Usage of -feedrate_rapid matter only when the preprocessor is using it, like -marlin-.']
     }
 
     def execute(self, args, unnamed_args):
@@ -186,6 +186,9 @@ class TclCommandDrillcncjob(TclCommandSignaled):
             if bool(args['dwell']) and args['dwelltime']:
                 job_obj.dwell = True
                 job_obj.dwelltime = float(args['dwelltime'])
+            else:
+                job_obj.dwell = obj.options["dwell"]
+                job_obj.dwelltime = float(obj.options["dwelltime"])
 
             job_obj.spindlespeed = args["spindlespeed"] if "spindlespeed" in args else None
             job_obj.pp_excellon_name = args["pp"] if "pp" in args and args["pp"] \
@@ -209,6 +212,18 @@ class TclCommandDrillcncjob(TclCommandSignaled):
             job_obj.generate_from_excellon_by_tool(obj, tools, drillz=drillz, toolchangez=toolchangez,
                                                    endz=endz,
                                                    toolchange=toolchange, excellon_optimization_type=opt_type)
+
+            for t_item in job_obj.exc_cnc_tools:
+                job_obj.exc_cnc_tools[t_item]['data']['offset'] = \
+                    float(job_obj.exc_cnc_tools[t_item]['offset_z']) + float(drillz)
+                job_obj.exc_cnc_tools[t_item]['data']['ppname_e'] = obj.options['ppname_e']
+
+                # for now there is no tool offset support in this Tcl Command so we write the 0.0 value here
+                job_obj.tool_offset[t_item] = 0.0
+
+            print(job_obj.tool_offset)
+            job_obj.origin_kind = 'excellon'
+
             job_obj.gcode_parse()
             job_obj.create_geometry()