Sfoglia il codice sorgente

- finished the work on file extensions registration with FlatCAM. If the file extensions are deleted in the Preferences -> File Associations then those extensions are unregistered with FlatCAM
- fixed bug in NCC Tools and in SolderPaste Tool if in Edit -> Preferences only one tool is entered

Marius Stanciu 6 anni fa
parent
commit
241cac8556
4 ha cambiato i file con 141 aggiunte e 57 eliminazioni
  1. 126 50
      FlatCAMApp.py
  2. 3 1
      README.md
  3. 8 2
      flatcamTools/ToolNonCopperClear.py
  4. 4 4
      flatcamTools/ToolSolderPaste.py

+ 126 - 50
FlatCAMApp.py

@@ -71,40 +71,6 @@ if '_' not in builtins.__dict__:
 # ########################################
 
 
-class ArgsThread(QtCore.QThread):
-    open_signal = pyqtSignal(list)
-
-    if sys.platform == 'win32':
-        address = (r'\\.\pipe\NPtest', 'AF_PIPE')
-    else:
-        address = ('/tmp/testipc', 'AF_UNIX')
-
-    def my_loop(self, address):
-        try:
-            listener = Listener(*address)
-            while True:
-                conn = listener.accept()
-                self.serve(conn)
-        except socket.error as e:
-            conn = Client(*address)
-            conn.send(sys.argv)
-            conn.send('close')
-            # close the current instance only if there are args
-            if len(sys.argv) > 1:
-                sys.exit()
-
-    def serve(self, conn):
-        while True:
-            msg = conn.recv()
-            if msg == 'close':
-                break
-            self.open_signal.emit(msg)
-        conn.close()
-
-    def run(self):
-        self.my_loop(self.address)
-
-
 class App(QtCore.QObject):
     """
     The main application class. The constructor starts the GUI.
@@ -754,10 +720,11 @@ class App(QtCore.QObject):
         self.defaults.set_change_callback(self.on_defaults_dict_change)  # When the dictionary changes.
         self.defaults.update({
             # Global APP Preferences
+            "first_run": True,
+            "units": "IN",
             "global_serial": 0,
             "global_stats": {},
             "global_tabs_detachable": True,
-            "units": "IN",
             "global_app_level": 'b',
             "global_portable": False,
             "global_language": 'English',
@@ -1800,6 +1767,15 @@ class App(QtCore.QObject):
 
         # when there are arguments at application startup this get launched
         self.args_at_startup.connect(lambda: self.on_startup_args())
+
+        # connect the 'Apply' buttons from the Preferences/File Associations
+        self.ui.fa_defaults_form.fa_excellon_group.exc_list_btn.clicked.connect(
+            lambda: self.on_register_files(obj_type='excellon'))
+        self.ui.fa_defaults_form.fa_gcode_group.gco_list_btn.clicked.connect(
+            lambda: self.on_register_files(obj_type='gcode'))
+        self.ui.fa_defaults_form.fa_gerber_group.grb_list_btn.clicked.connect(
+            lambda: self.on_register_files(obj_type='gerber'))
+
         self.log.debug("Finished connecting Signals.")
 
         # this is a flag to signal to other tools that the ui tooltab is locked and not accessible
@@ -2127,7 +2103,11 @@ class App(QtCore.QObject):
         # ################################################
         # ######### Variables for global usage ###########
         # ################################################
-        self.on_apply_associations()
+
+        # register files with FlatCAM; it works only for Windows for now
+        if sys.platform == 'win32' and self.defaults["first_run"] is True:
+            self.on_register_files()
+
         # coordinates for relative position display
         self.rel_point1 = (0, 0)
         self.rel_point2 = (0, 0)
@@ -2245,6 +2225,9 @@ class App(QtCore.QObject):
 
         self.set_ui_title(name=_("New Project - Not saved"))
 
+        # after the first run, this object should be False
+        self.defaults["first_run"] = False
+
         # 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:
@@ -3896,7 +3879,9 @@ class App(QtCore.QObject):
         else:
             self.ui.shell_dock.show()
 
-    def on_apply_associations(self):
+    def on_register_files(self, obj_type=None):
+        log.debug("Manufacturing files extensions are registered with FlatCAM.")
+
         new_reg_path = 'Software\\Classes\\'
         # find if the current user is admin
         try:
@@ -3919,20 +3904,77 @@ class App(QtCore.QObject):
             except WindowsError:
                 return False
 
-        exc_list = self.ui.fa_defaults_form.fa_excellon_group.exc_list_text.get_value().split(',')
-        for ext in exc_list:
-            new_k = new_reg_path + ext.replace(' ', '')
-            set_reg('', root_path=root_path, new_reg_path=new_k, value='FlatCAM')
-
-        gco_list = self.ui.fa_defaults_form.fa_gcode_group.gco_list_text.get_value().split(',')
-        for ext in gco_list:
-            new_k = new_reg_path + ext.replace(' ', '')
-            set_reg('', root_path=root_path, new_reg_path=new_k, value='FlatCAM')
+        # delete key in registry
+        def delete_reg(root_path, reg_path, key_to_del):
+            key_to_del_path = reg_path + key_to_del
+            try:
+                winreg.DeleteKey(root_path, key_to_del_path)
+                return True
+            except WindowsError:
+                return False
 
-        grb_list = self.ui.fa_defaults_form.fa_gerber_group.grb_list_text.get_value().split(',')
-        for ext in grb_list:
-            new_k = new_reg_path + ext.replace(' ', '')
-            set_reg('', root_path=root_path, new_reg_path=new_k, value='FlatCAM')
+        if obj_type is None or obj_type == 'excellon':
+            exc_list = self.ui.fa_defaults_form.fa_excellon_group.exc_list_text.get_value().replace(' ', '').split(',')
+            exc_list = [x for x in exc_list if x != '']
+
+            # register all keys in the Preferences window
+            for ext in exc_list:
+                new_k = new_reg_path + ext
+                set_reg('', root_path=root_path, new_reg_path=new_k, value='FlatCAM')
+
+            # and unregister those that are no longer in the Preferences windows but are in the file
+            for ext in self.defaults["fa_excellon"].replace(' ', '').split(','):
+                if ext not in exc_list:
+                    delete_reg(root_path=root_path, reg_path=new_reg_path, key_to_del=ext)
+
+            # now write the updated extensions to the self.defaults
+            new_ext = ''
+            for ext in exc_list:
+                new_ext = new_ext + ext + ', '
+            self.defaults["fa_excellon"] = new_ext
+            self.inform.emit(_("[success] Selected Excellon file extensions registered with FlatCAM."))
+
+        if obj_type is None or obj_type == 'gcode':
+            gco_list = self.ui.fa_defaults_form.fa_gcode_group.gco_list_text.get_value().replace(' ', '').split(',')
+            gco_list = [x for x in gco_list if x != '']
+
+            # register all keys in the Preferences window
+            for ext in gco_list:
+                new_k = new_reg_path + ext
+                set_reg('', root_path=root_path, new_reg_path=new_k, value='FlatCAM')
+
+            # and unregister those that are no longer in the Preferences windows but are in the file
+            for ext in self.defaults["fa_gcode"].replace(' ', '').split(','):
+                if ext not in gco_list:
+                    delete_reg(root_path=root_path, reg_path=new_reg_path, key_to_del=ext)
+
+            # now write the updated extensions to the self.defaults
+            new_ext = ''
+            for ext in gco_list:
+                new_ext = new_ext + ext + ', '
+            self.defaults["fa_gcode"] = new_ext
+            self.inform.emit(_("[success] Selected GCode file extensions registered with FlatCAM."))
+
+        if obj_type is None or obj_type == 'gerber':
+            grb_list = self.ui.fa_defaults_form.fa_gerber_group.grb_list_text.get_value().replace(' ', '').split(',')
+            grb_list = [x for x in grb_list if x != '']
+
+            # register all keys in the Preferences window
+            for ext in grb_list:
+                new_k = new_reg_path + ext
+                set_reg('', root_path=root_path, new_reg_path=new_k, value='FlatCAM')
+
+            # and unregister those that are no longer in the Preferences windows but are in the file
+            for ext in self.defaults["fa_gerber"].replace(' ', '').split(','):
+                if ext not in grb_list:
+                    delete_reg(root_path=root_path, reg_path=new_reg_path, key_to_del=ext)
+
+            # now write the updated extensions to the self.defaults
+            new_ext = ''
+            for ext in grb_list:
+                new_ext = new_ext + ext + ', '
+            self.defaults["fa_gerber"] = new_ext
+            self.inform.emit(_("[success] Selected Gerber file extensions registered with FlatCAM."))
 
     def on_edit_join(self, name=None):
         """
@@ -9588,4 +9630,38 @@ The normal flow when working in FlatCAM is the following:</span></p>
                 obj.options[oname] = self.defaults[option]
         obj.to_form()  # Update UI
 
+
+class ArgsThread(QtCore.QThread):
+    open_signal = pyqtSignal(list)
+
+    if sys.platform == 'win32':
+        address = (r'\\.\pipe\NPtest', 'AF_PIPE')
+    else:
+        address = ('/tmp/testipc', 'AF_UNIX')
+
+    def my_loop(self, address):
+        try:
+            listener = Listener(*address)
+            while True:
+                conn = listener.accept()
+                self.serve(conn)
+        except socket.error as e:
+            conn = Client(*address)
+            conn.send(sys.argv)
+            conn.send('close')
+            # close the current instance only if there are args
+            if len(sys.argv) > 1:
+                sys.exit()
+
+    def serve(self, conn):
+        while True:
+            msg = conn.recv()
+            if msg == 'close':
+                break
+            self.open_signal.emit(msg)
+        conn.close()
+
+    def run(self):
+        self.my_loop(self.address)
+
 # end of file

+ 3 - 1
README.md

@@ -20,13 +20,15 @@ CAD program, and create G-Code for Isolation routing.
 - in NCC Tool added a warning in case there are isolation tools and if those isolation's are interrupted by an area or a box
 - in Paint Tool made that the area selection is repeated until RMB click
 - in Paint Tool and NCC Tool fixed the RMB click detection when Area selection is used
+- finished the work on file extensions registration with FlatCAM. If the file extensions are deleted in the Preferences -> File Associations then those extensions are unregistered with FlatCAM
+- fixed bug in NCC Tools and in SolderPaste Tool if in Edit -> Preferences only one tool is entered
 
 2.09.2019
 
 - fixed issue in NCC Tool when using area option
 - added formatting for some strings in the app strings, making the future translations easier
 - made changes in the Excellon Tools Table to make it more clear that the tools are selected in the # column and not in the Plot column
-- in Excellon and Gerber Seleted tab made the Plot (mark) columns not selectable
+- in Excellon and Gerber Selected tab made the Plot (mark) columns not selectable
 - some ToolTips were modified
 - in Properties Tool made threaded the calculation of convex_hull area and also made it to work for multi-geo objects
 - in NCC tool the type of tool that is used is transferred to the Geometry object

+ 8 - 2
flatcamTools/ToolNonCopperClear.py

@@ -1488,7 +1488,10 @@ class NonCopperClear(FlatCAMTool, Gerber):
             # Generate area for each tool
             offset = sum(sorted_tools)
             current_uid = int(1)
-            tool = eval(self.app.defaults["tools_ncctools"])[0]
+            try:
+                tool = eval(self.app.defaults["tools_ncctools"])[0]
+            except TypeError:
+                tool = eval(self.app.defaults["tools_ncctools"])
 
             # ###################################################################################################
             # Calculate the empty area by subtracting the solid_geometry from the object bounding box geometry ##
@@ -1715,7 +1718,10 @@ class NonCopperClear(FlatCAMTool, Gerber):
             cleared_by_last_tool = []
             rest_geo = []
             current_uid = 1
-            tool = eval(self.app.defaults["tools_ncctools"])[0]
+            try:
+                tool = eval(self.app.defaults["tools_ncctools"])[0]
+            except TypeError:
+                tool = eval(self.app.defaults["tools_ncctools"])
 
             # repurposed flag for final object, geo_obj. True if it has any solid_geometry, False if not.
             app_obj.poly_not_cleared = True

+ 4 - 4
flatcamTools/ToolSolderPaste.py

@@ -1124,7 +1124,7 @@ class SolderPaste(FlatCAMTool):
             # some or all the pads are not covered with solder paste
             if work_geo:
                 app_obj.inform.emit(_("[WARNING_NOTCL] Some or all pads have no solder "
-                                    "due of inadequate nozzle diameters..."))
+                                      "due of inadequate nozzle diameters..."))
                 return 'fail'
 
         if use_thread:
@@ -1300,11 +1300,11 @@ class SolderPaste(FlatCAMTool):
         try:
             if obj.special_group != 'solder_paste_tool':
                 self.app.inform.emit(_("[WARNING_NOTCL] This CNCJob object can't be processed. "
-                                     "NOT a solder_paste_tool CNCJob object."))
+                                       "NOT a solder_paste_tool CNCJob object."))
                 return
         except AttributeError:
             self.app.inform.emit(_("[WARNING_NOTCL] This CNCJob object can't be processed. "
-                                 "NOT a solder_paste_tool CNCJob object."))
+                                   "NOT a solder_paste_tool CNCJob object."))
             return
 
         gcode = '(G-CODE GENERATED BY FLATCAM v%s - www.flatcam.org - Version Date: %s)\n' % \
@@ -1356,7 +1356,7 @@ class SolderPaste(FlatCAMTool):
 
         if obj.special_group != 'solder_paste_tool':
             self.app.inform.emit(_("[WARNING_NOTCL] This CNCJob object can't be processed. "
-                                 "NOT a solder_paste_tool CNCJob object."))
+                                   "NOT a solder_paste_tool CNCJob object."))
             return
 
         _filter_ = "G-Code Files (*.nc);;G-Code Files (*.txt);;G-Code Files (*.tap);;G-Code Files (*.cnc);;" \