Explorar o código

- 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

Marius Stanciu %!s(int64=6) %!d(string=hai) anos
pai
achega
8958ef8007
Modificáronse 4 ficheiros con 291 adicións e 56 borrados
  1. 161 34
      FlatCAMApp.py
  2. 4 0
      README.md
  3. 9 8
      flatcamEditors/FlatCAMGrbEditor.py
  4. 117 14
      flatcamGUI/FlatCAMGUI.py

+ 161 - 34
FlatCAMApp.py

@@ -1163,12 +1163,13 @@ class App(QtCore.QObject):
             "tools_sub_close_paths": True,
             "tools_sub_close_paths": True,
 
 
             # file associations
             # file associations
-            "fa_excellon": ".drl, .xln, .drd, .tap, .exc, .ncd",
-            "fa_gcode": ".nc, .ncc, .tap, .gcode, .cnc, .ecs, .fnc, .dnc, .ncg, .gc, .fan, .fgc, .din, .xpi,"
-                        " .hnc, .h, .i, .ncp, .min, .gcd, .rol, .mpr, .ply, .out, .eia, .plt, .sbp, .mpf",
-            "fa_gerber": ".gbr, .ger, .gtl, .gbl, .gts, .gbs, .gtp, .gbp, .gto, .gbo, .gm1, .gml, .gm3, .gko, .cmp, "
-                         ".sol, .stc, .sts, .plc, .pls, .crc, .crs, .tsm, .bsm, .ly2, .ly15, .dim, .mil, .grb, .top, "
-                         ".bot, .smt, .smb, .sst, .ssb, .spt, .spb, .pho, .gdo, .art, .gbd",
+            "fa_excellon": 'drd, drl, exc, ncd, tap, xln',
+            "fa_gcode": 'cnc, din, dnc, ecs, eia, fan, fgc, fnc, gc, gcd, gcode, h, hnc, i, min, mpf, mpr, nc, ncc, '
+                        'ncg, ncp, out, plt, ply, rol, sbp, tap, xpi',
+            "fa_gerber": 'art, bot, bsm, cmp, crc, crs, dim, g4, gb0, gb1, gb2, gb3, gb5, gb6, gb7, gb8, gb9, gbd, '
+                         'gbl, gbo, gbp, gbr, gbs, gdo, ger, gko, gm1, gm2, gm3, grb, gtl, gto, gtp, gts, ly15, ly2, '
+                         'mil, pho, plc, pls, smb, smt, sol, spb, spt, ssb, sst, stc, sts, top, tsm'
+,
         })
         })
 
 
         # ############################################################
         # ############################################################
@@ -1913,6 +1914,38 @@ class App(QtCore.QObject):
         # 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(self.on_startup_args)
         self.args_at_startup[list].connect(self.on_startup_args)
 
 
+        # ##############################################################
+        # ############### FILE ASSOCIATIONS SIGNALS ####################
+        # ##############################################################
+
+        self.ui.fa_defaults_form.fa_excellon_group.restore_btn.clicked.connect(
+            lambda: self.restore_extensions(ext_type='excellon'))
+        self.ui.fa_defaults_form.fa_gcode_group.restore_btn.clicked.connect(
+            lambda: self.restore_extensions(ext_type='gcode'))
+        self.ui.fa_defaults_form.fa_gerber_group.restore_btn.clicked.connect(
+            lambda: self.restore_extensions(ext_type='gerber'))
+
+        self.ui.fa_defaults_form.fa_excellon_group.del_all_btn.clicked.connect(
+            lambda: self.delete_all_extensions(ext_type='excellon'))
+        self.ui.fa_defaults_form.fa_gcode_group.del_all_btn.clicked.connect(
+            lambda: self.delete_all_extensions(ext_type='gcode'))
+        self.ui.fa_defaults_form.fa_gerber_group.del_all_btn.clicked.connect(
+            lambda: self.delete_all_extensions(ext_type='gerber'))
+
+        self.ui.fa_defaults_form.fa_excellon_group.add_btn.clicked.connect(
+            lambda: self.add_extension(ext_type='excellon'))
+        self.ui.fa_defaults_form.fa_gcode_group.add_btn.clicked.connect(
+            lambda: self.add_extension(ext_type='gcode'))
+        self.ui.fa_defaults_form.fa_gerber_group.add_btn.clicked.connect(
+            lambda: self.add_extension(ext_type='gerber'))
+
+        self.ui.fa_defaults_form.fa_excellon_group.del_btn.clicked.connect(
+            lambda: self.del_extension(ext_type='excellon'))
+        self.ui.fa_defaults_form.fa_gcode_group.del_btn.clicked.connect(
+            lambda: self.del_extension(ext_type='gcode'))
+        self.ui.fa_defaults_form.fa_gerber_group.del_btn.clicked.connect(
+            lambda: self.del_extension(ext_type='gerber'))
+
         # 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(
             lambda: self.on_register_files(obj_type='excellon'))
             lambda: self.on_register_files(obj_type='excellon'))
@@ -2312,16 +2345,16 @@ class App(QtCore.QObject):
         # if Preferences are changed in the Edit -> Preferences tab the value will be set to True
         # if Preferences are changed in the Edit -> Preferences tab the value will be set to True
         self.preferences_changed_flag = False
         self.preferences_changed_flag = False
 
 
-        self.grb_list = ['gbr', 'ger', 'gtl', 'gbl', 'gts', 'gbs', 'gtp', 'gbp', 'gto', 'gbo', 'gm1', 'gm2', 'gm3',
-                         'gko', 'cmp', 'sol', 'stc', 'sts', 'plc', 'pls', 'crc', 'crs', 'tsm', 'bsm', 'ly2', 'ly15',
-                         'dim', 'mil', 'grb', 'top', 'bot', 'smt', 'smb', 'sst', 'ssb', 'spt', 'spb', 'pho', 'gdo',
-                         'art', 'gbd', 'gb0', 'gb1', 'gb2', 'gb3', 'g4', 'gb5', 'gb6', 'gb7', 'gb8', 'gb9'
-                         ]
-        self.exc_list = ['drl', 'txt', 'xln', 'drd', 'tap', 'exc', 'ncd']
-        self.gcode_list = ['nc', 'ncc', 'tap', 'gcode', 'cnc', 'ecs', 'fnc', 'dnc', 'ncg', 'gc', 'fan', 'fgc', 'din',
-                           'xpi', 'hnc', 'h', 'i', 'ncp', 'min', 'gcd', 'rol', 'mpr', 'ply', 'out', 'eia', 'plt', 'sbp',
-                           'mpf'
-                           ]
+        self.grb_list = ['art', 'bot', 'bsm', 'cmp', 'crc', 'crs', 'dim', 'g4', 'gb0', 'gb1', 'gb2', 'gb3', 'gb5',
+                         'gb6', 'gb7', 'gb8', 'gb9', 'gbd', 'gbl', 'gbo', 'gbp', 'gbr', 'gbs', 'gdo', 'ger', 'gko',
+                         'gml', 'gm1', 'gm2', 'gm3', 'grb', 'gtl', 'gto', 'gtp', 'gts', 'ly15', 'ly2', 'mil', 'pho',
+                         'plc', 'pls', 'smb', 'smt', 'sol', 'spb', 'spt', 'ssb', 'sst', 'stc', 'sts', 'top', 'tsm']
+
+        self.exc_list = ['drd', 'drl', 'exc', 'ncd', 'tap', 'txt', 'xln']
+
+        self.gcode_list = ['cnc', 'din', 'dnc', 'ecs', 'eia', 'fan', 'fgc', 'fnc', 'gc', 'gcd', 'gcode', 'h', 'hnc',
+                           'i', 'min', 'mpf', 'mpr', 'nc', 'ncc', 'ncg', 'ncp', 'out', 'plt', 'ply', 'rol', 'sbp',
+                           'tap', 'xpi']
         self.svg_list = ['svg']
         self.svg_list = ['svg']
         self.dxf_list = ['dxf']
         self.dxf_list = ['dxf']
         self.pdf_list = ['pdf']
         self.pdf_list = ['pdf']
@@ -4582,19 +4615,19 @@ class App(QtCore.QObject):
 
 
             # register all keys in the Preferences window
             # register all keys in the Preferences window
             for ext in exc_list:
             for ext in exc_list:
-                new_k = new_reg_path + ext
+                new_k = new_reg_path + '.%s' % ext
                 set_reg('', root_path=root_path, new_reg_path=new_k, value='FlatCAM')
                 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
             # 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(','):
             for ext in self.defaults["fa_excellon"].replace(' ', '').split(','):
                 if ext not in exc_list:
                 if ext not in exc_list:
-                    delete_reg(root_path=root_path, reg_path=new_reg_path, key_to_del=ext)
+                    delete_reg(root_path=root_path, reg_path=new_reg_path, key_to_del='.%s' % ext)
 
 
             # now write the updated extensions to the self.defaults
             # 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
+            # new_ext = ''
+            # for ext in exc_list:
+            #     new_ext = new_ext + ext + ', '
+            # self.defaults["fa_excellon"] = new_ext
             self.inform.emit('[success] %s' % _("Selected Excellon file extensions registered with FlatCAM."))
             self.inform.emit('[success] %s' % _("Selected Excellon file extensions registered with FlatCAM."))
 
 
         if obj_type is None or obj_type == 'gcode':
         if obj_type is None or obj_type == 'gcode':
@@ -4603,19 +4636,19 @@ class App(QtCore.QObject):
 
 
             # register all keys in the Preferences window
             # register all keys in the Preferences window
             for ext in gco_list:
             for ext in gco_list:
-                new_k = new_reg_path + ext
+                new_k = new_reg_path + '.%s' % ext
                 set_reg('', root_path=root_path, new_reg_path=new_k, value='FlatCAM')
                 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
             # 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(','):
             for ext in self.defaults["fa_gcode"].replace(' ', '').split(','):
                 if ext not in gco_list:
                 if ext not in gco_list:
-                    delete_reg(root_path=root_path, reg_path=new_reg_path, key_to_del=ext)
+                    delete_reg(root_path=root_path, reg_path=new_reg_path, key_to_del='.%s' % ext)
 
 
             # now write the updated extensions to the self.defaults
             # 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
+            # new_ext = ''
+            # for ext in gco_list:
+            #     new_ext = new_ext + ext + ', '
+            # self.defaults["fa_gcode"] = new_ext
             self.inform.emit('[success] %s' %
             self.inform.emit('[success] %s' %
                              _("Selected GCode file extensions registered with FlatCAM."))
                              _("Selected GCode file extensions registered with FlatCAM."))
 
 
@@ -4625,22 +4658,116 @@ class App(QtCore.QObject):
 
 
             # register all keys in the Preferences window
             # register all keys in the Preferences window
             for ext in grb_list:
             for ext in grb_list:
-                new_k = new_reg_path + ext
+                new_k = new_reg_path + '.%s' % ext
                 set_reg('', root_path=root_path, new_reg_path=new_k, value='FlatCAM')
                 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
             # 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(','):
             for ext in self.defaults["fa_gerber"].replace(' ', '').split(','):
                 if ext not in grb_list:
                 if ext not in grb_list:
-                    delete_reg(root_path=root_path, reg_path=new_reg_path, key_to_del=ext)
+                    delete_reg(root_path=root_path, reg_path=new_reg_path, key_to_del='.%s' % ext)
 
 
             # now write the updated extensions to the self.defaults
             # 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
+            # new_ext = ''
+            # for ext in grb_list:
+            #     new_ext = new_ext + ext + ', '
+            # self.defaults["fa_gerber"] = new_ext
             self.inform.emit('[success] %s' %
             self.inform.emit('[success] %s' %
                              _("Selected Gerber file extensions registered with FlatCAM."))
                              _("Selected Gerber file extensions registered with FlatCAM."))
 
 
+    def add_extension(self, ext_type):
+        if ext_type == 'excellon':
+            new_ext = self.ui.fa_defaults_form.fa_excellon_group.ext_entry.get_value()
+            if new_ext == '':
+                return
+
+            old_val = self.ui.fa_defaults_form.fa_excellon_group.exc_list_text.get_value().replace(' ', '').split(',')
+            if new_ext in old_val:
+                return
+            old_val.append(new_ext)
+            old_val.sort()
+            self.ui.fa_defaults_form.fa_excellon_group.exc_list_text.set_value(', '.join(old_val))
+        if ext_type == 'gcode':
+            new_ext = self.ui.fa_defaults_form.fa_gcode_group.ext_entry.get_value()
+            if new_ext == '':
+                return
+
+            old_val = self.ui.fa_defaults_form.fa_gcode_group.gco_list_text.get_value().replace(' ', '').split(',')
+            if new_ext in old_val:
+                return
+            old_val.append(new_ext)
+            old_val.sort()
+            self.ui.fa_defaults_form.fa_gcode_group.gco_list_text.set_value(', '.join(old_val))
+        if ext_type == 'gerber':
+            new_ext = self.ui.fa_defaults_form.fa_gerber_group.ext_entry.get_value()
+            if new_ext == '':
+                return
+
+            old_val = self.ui.fa_defaults_form.fa_gerber_group.grb_list_text.get_value().replace(' ', '').split(',')
+            if new_ext in old_val:
+                return
+            old_val.append(new_ext)
+            old_val.sort()
+            self.ui.fa_defaults_form.fa_gerber_group.grb_list_text.set_value(', '.join(old_val))
+
+    def del_extension(self, ext_type):
+        if ext_type == 'excellon':
+            new_ext = self.ui.fa_defaults_form.fa_excellon_group.ext_entry.get_value()
+            if new_ext == '':
+                return
+
+            old_val = self.ui.fa_defaults_form.fa_excellon_group.exc_list_text.get_value().replace(' ', '').split(',')
+            if new_ext not in old_val:
+                return
+            old_val.remove(new_ext)
+            old_val.sort()
+            self.ui.fa_defaults_form.fa_excellon_group.exc_list_text.set_value(', '.join(old_val))
+        if ext_type == 'gcode':
+            new_ext = self.ui.fa_defaults_form.fa_gcode_group.ext_entry.get_value()
+            if new_ext == '':
+                return
+
+            old_val = self.ui.fa_defaults_form.fa_gcode_group.gco_list_text.get_value().replace(' ', '').split(',')
+            if new_ext not in old_val:
+                return
+            old_val.remove(new_ext)
+            old_val.sort()
+            self.ui.fa_defaults_form.fa_gcode_group.gco_list_text.set_value(', '.join(old_val))
+        if ext_type == 'gerber':
+            new_ext = self.ui.fa_defaults_form.fa_gerber_group.ext_entry.get_value()
+            if new_ext == '':
+                return
+
+            old_val = self.ui.fa_defaults_form.fa_gerber_group.grb_list_text.get_value().replace(' ', '').split(',')
+            if new_ext not in old_val:
+                return
+            old_val.remove(new_ext)
+            old_val.sort()
+            self.ui.fa_defaults_form.fa_gerber_group.grb_list_text.set_value(', '.join(old_val))
+
+    def restore_extensions(self, ext_type):
+        if ext_type == 'excellon':
+            # don't add 'txt' to the associations (too many files are .txt and not Excellon) but keep it in the list
+            # for the ability to open Excellon files with .txt extension
+            new_exc_list = deepcopy(self.exc_list)
+
+            try:
+                new_exc_list.remove('txt')
+            except ValueError:
+                pass
+            self.ui.fa_defaults_form.fa_excellon_group.exc_list_text.set_value(', '.join(new_exc_list))
+        if ext_type == 'gcode':
+            self.ui.fa_defaults_form.fa_gcode_group.gco_list_text.set_value(', '.join(self.gcode_list))
+        if ext_type == 'gerber':
+            self.ui.fa_defaults_form.fa_gerber_group.grb_list_text.set_value(', '.join(self.grb_list))
+
+    def delete_all_extensions(self, ext_type):
+        if ext_type == 'excellon':
+            self.ui.fa_defaults_form.fa_excellon_group.exc_list_text.set_value('')
+        if ext_type == 'gcode':
+            self.ui.fa_defaults_form.fa_gcode_group.gco_list_text.set_value('')
+        if ext_type == 'gerber':
+            self.ui.fa_defaults_form.fa_gerber_group.grb_list_text.set_value('')
+
     def on_edit_join(self, name=None):
     def on_edit_join(self, name=None):
         """
         """
         Callback for Edit->Join. Joins the selected geometry objects into
         Callback for Edit->Join. Joins the selected geometry objects into

+ 4 - 0
README.md

@@ -9,6 +9,10 @@ CAD program, and create G-Code for Isolation routing.
 
 
 =================================================
 =================================================
 
 
+18.09.2019
+
+- added more funtionality to the Extension registration with FLatCAM and added to the GUI in Edit -> Preferences -> Utilities
+
 17.09.2019
 17.09.2019
 
 
 - added more programmers that contributed to FlatCAM over the years, in the "About FlatCAM" -> Programmers window
 - added more programmers that contributed to FlatCAM over the years, in the "About FlatCAM" -> Programmers window

+ 9 - 8
flatcamEditors/FlatCAMGrbEditor.py

@@ -3742,7 +3742,6 @@ class FlatCAMGrbEditor(QtCore.QObject):
                 #             temp_elem.append(deepcopy(new_elem))
                 #             temp_elem.append(deepcopy(new_elem))
                 for elem in self.gerber_obj.apertures[apid]['geometry']:
                 for elem in self.gerber_obj.apertures[apid]['geometry']:
                     new_elem = dict()
                     new_elem = dict()
-
                     if 'solid' in elem:
                     if 'solid' in elem:
                         solid_geo = elem['solid']
                         solid_geo = elem['solid']
                         for clear_geo in global_clear_geo:
                         for clear_geo in global_clear_geo:
@@ -4434,16 +4433,18 @@ class FlatCAMGrbEditor(QtCore.QObject):
                             self.plot_shape(geometry=geometric_data,
                             self.plot_shape(geometry=geometric_data,
                                             color=self.app.defaults['global_sel_draw_color'],
                                             color=self.app.defaults['global_sel_draw_color'],
                                             linewidth=2)
                                             linewidth=2)
-                            continue
-                        self.plot_shape(geometry=geometric_data,
-                                        color=self.app.defaults['global_draw_color'])
+
+                        else:
+                            self.plot_shape(geometry=geometric_data,
+                                            color=self.app.defaults['global_draw_color'])
                 except KeyError:
                 except KeyError:
                     pass
                     pass
 
 
-            for elem in self.utility:
-                geometric_data = elem.geo['solid']
-                self.plot_shape(geometry=geometric_data, linewidth=1)
-                continue
+            if self.utility:
+                for elem in self.utility:
+                    geometric_data = elem.geo['solid']
+                    self.plot_shape(geometry=geometric_data, linewidth=1)
+                    continue
 
 
             self.shapes.redraw()
             self.shapes.redraw()
 
 

+ 117 - 14
flatcamGUI/FlatCAMGUI.py

@@ -958,7 +958,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
 
 
         self.fa_tab = QtWidgets.QWidget()
         self.fa_tab = QtWidgets.QWidget()
         self.fa_tab.setObjectName("fa_tab")
         self.fa_tab.setObjectName("fa_tab")
-        self.pref_tab_area.addTab(self.fa_tab, _("FILE ASSOCIATIONS"))
+        self.pref_tab_area.addTab(self.fa_tab, _("UTILITIES"))
         self.fa_tab_lay = QtWidgets.QVBoxLayout()
         self.fa_tab_lay = QtWidgets.QVBoxLayout()
         self.fa_tab_lay.setContentsMargins(2, 2, 2, 2)
         self.fa_tab_lay.setContentsMargins(2, 2, 2, 2)
         self.fa_tab.setLayout(self.fa_tab_lay)
         self.fa_tab.setLayout(self.fa_tab_lay)
@@ -7794,34 +7794,77 @@ class ToolsSubPrefGroupUI(OptionsGroupUI):
 class FAExcPrefGroupUI(OptionsGroupUI):
 class FAExcPrefGroupUI(OptionsGroupUI):
     def __init__(self, parent=None):
     def __init__(self, parent=None):
         # OptionsGroupUI.__init__(self, "Excellon File associations Preferences", parent=None)
         # OptionsGroupUI.__init__(self, "Excellon File associations Preferences", parent=None)
-        super(FAExcPrefGroupUI, self).__init__(self)
+        super().__init__(self)
 
 
         self.setTitle(str(_("Excellon File associations")))
         self.setTitle(str(_("Excellon File associations")))
 
 
-        # ## Export G-Code
-        self.exc_list_label = QtWidgets.QLabel("<b>%s:</b>" % _("Extensions list"))
-        self.exc_list_label.setToolTip(
+        self.layout.setContentsMargins(2, 2, 2, 2)
+
+        self.vertical_lay = QtWidgets.QVBoxLayout()
+        scroll_widget = QtWidgets.QWidget()
+
+        scroll = VerticalScrollArea()
+        scroll.setWidget(scroll_widget)
+        scroll.setWidgetResizable(True)
+        scroll.setFrameShape(QtWidgets.QFrame.NoFrame)
+
+        self.restore_btn = FCButton(_("Restore"))
+        self.restore_btn.setToolTip(_("Restore the extension list to the default state."))
+        self.del_all_btn = FCButton(_("Delete All"))
+        self.del_all_btn.setToolTip(_("Delete all extensions from the list."))
+
+        hlay0 = QtWidgets.QHBoxLayout()
+        hlay0.addWidget(self.restore_btn)
+        hlay0.addWidget(self.del_all_btn)
+        self.vertical_lay.addLayout(hlay0)
+
+        # # ## Excellon associations
+        list_label = QtWidgets.QLabel("<b>%s:</b>" % _("Extensions list"))
+        list_label.setToolTip(
             _("List of file extensions to be\n"
             _("List of file extensions to be\n"
               "associated with FlatCAM.")
               "associated with FlatCAM.")
         )
         )
-        self.layout.addWidget(self.exc_list_label)
+        self.vertical_lay.addWidget(list_label)
 
 
         self.exc_list_text = FCTextArea()
         self.exc_list_text = FCTextArea()
+        self.exc_list_text.setReadOnly(True)
         # self.exc_list_text.sizeHint(custom_sizehint=150)
         # self.exc_list_text.sizeHint(custom_sizehint=150)
         font = QtGui.QFont()
         font = QtGui.QFont()
         font.setPointSize(12)
         font.setPointSize(12)
         self.exc_list_text.setFont(font)
         self.exc_list_text.setFont(font)
 
 
-        self.layout.addWidget(self.exc_list_text)
+        self.vertical_lay.addWidget(self.exc_list_text)
+
+        self.ext_label = QtWidgets.QLabel('%s:' % _("Extension"))
+        self.ext_label.setToolTip(_("A file extension to be added or deleted to the list."))
+        self.ext_entry = FCEntry()
+
+        hlay1 = QtWidgets.QHBoxLayout()
+        self.vertical_lay.addLayout(hlay1)
+        hlay1.addWidget(self.ext_label)
+        hlay1.addWidget(self.ext_entry)
+
+        self.add_btn = FCButton(_("Add Extension"))
+        self.add_btn.setToolTip(_("Add a file extension to the list"))
+        self.del_btn = FCButton(_("Delete Extension"))
+        self.del_btn.setToolTip(_("Delete a file extension from the list"))
+
+        hlay2 = QtWidgets.QHBoxLayout()
+        self.vertical_lay.addLayout(hlay2)
+        hlay2.addWidget(self.add_btn)
+        hlay2.addWidget(self.del_btn)
 
 
-        self.exc_list_btn = FCButton(_("Apply"))
+        self.exc_list_btn = FCButton(_("Apply Association"))
         self.exc_list_btn.setToolTip(_("Apply the file associations between\n"
         self.exc_list_btn.setToolTip(_("Apply the file associations between\n"
                                        "FlatCAM and the files with above extensions.\n"
                                        "FlatCAM and the files with above extensions.\n"
                                        "They will be active after next logon.\n"
                                        "They will be active after next logon.\n"
                                        "This work only in Windows."))
                                        "This work only in Windows."))
-        self.layout.addWidget(self.exc_list_btn)
+        self.vertical_lay.addWidget(self.exc_list_btn)
 
 
-        # self.layout.addStretch()
+        scroll_widget.setLayout(self.vertical_lay)
+        self.layout.addWidget(scroll)
+
+        # self.vertical_lay.addStretch()
 
 
 
 
 class FAGcoPrefGroupUI(OptionsGroupUI):
 class FAGcoPrefGroupUI(OptionsGroupUI):
@@ -7831,7 +7874,17 @@ class FAGcoPrefGroupUI(OptionsGroupUI):
 
 
         self.setTitle(str(_("GCode File associations")))
         self.setTitle(str(_("GCode File associations")))
 
 
-        # ## Export G-Code
+        self.restore_btn = FCButton(_("Restore"))
+        self.restore_btn.setToolTip(_("Restore the extension list to the default state."))
+        self.del_all_btn = FCButton(_("Delete All"))
+        self.del_all_btn.setToolTip(_("Delete all extensions from the list."))
+
+        hlay0 = QtWidgets.QHBoxLayout()
+        self.layout.addLayout(hlay0)
+        hlay0.addWidget(self.restore_btn)
+        hlay0.addWidget(self.del_all_btn)
+
+        # ## G-Code associations
         self.gco_list_label = QtWidgets.QLabel("<b>%s:</b>" % _("Extensions list"))
         self.gco_list_label = QtWidgets.QLabel("<b>%s:</b>" % _("Extensions list"))
         self.gco_list_label.setToolTip(
         self.gco_list_label.setToolTip(
             _("List of file extensions to be\n"
             _("List of file extensions to be\n"
@@ -7840,6 +7893,7 @@ class FAGcoPrefGroupUI(OptionsGroupUI):
         self.layout.addWidget(self.gco_list_label)
         self.layout.addWidget(self.gco_list_label)
 
 
         self.gco_list_text = FCTextArea()
         self.gco_list_text = FCTextArea()
+        self.gco_list_text.setReadOnly(True)
         # self.gco_list_text.sizeHint(custom_sizehint=150)
         # self.gco_list_text.sizeHint(custom_sizehint=150)
         font = QtGui.QFont()
         font = QtGui.QFont()
         font.setPointSize(12)
         font.setPointSize(12)
@@ -7847,7 +7901,26 @@ class FAGcoPrefGroupUI(OptionsGroupUI):
 
 
         self.layout.addWidget(self.gco_list_text)
         self.layout.addWidget(self.gco_list_text)
 
 
-        self.gco_list_btn = FCButton(_("Apply"))
+        self.ext_label = QtWidgets.QLabel('%s:' % _("Extension"))
+        self.ext_label.setToolTip(_("A file extension to be added or deleted to the list."))
+        self.ext_entry = FCEntry()
+
+        hlay1 = QtWidgets.QHBoxLayout()
+        self.layout.addLayout(hlay1)
+        hlay1.addWidget(self.ext_label)
+        hlay1.addWidget(self.ext_entry)
+
+        self.add_btn = FCButton(_("Add Extension"))
+        self.add_btn.setToolTip(_("Add a file extension to the list"))
+        self.del_btn = FCButton(_("Delete Extension"))
+        self.del_btn.setToolTip(_("Delete a file extension from the list"))
+
+        hlay2 = QtWidgets.QHBoxLayout()
+        self.layout.addLayout(hlay2)
+        hlay2.addWidget(self.add_btn)
+        hlay2.addWidget(self.del_btn)
+
+        self.gco_list_btn = FCButton(_("Apply Association"))
         self.gco_list_btn.setToolTip(_("Apply the file associations between\n"
         self.gco_list_btn.setToolTip(_("Apply the file associations between\n"
                                        "FlatCAM and the files with above extensions.\n"
                                        "FlatCAM and the files with above extensions.\n"
                                        "They will be active after next logon.\n"
                                        "They will be active after next logon.\n"
@@ -7864,7 +7937,17 @@ class FAGrbPrefGroupUI(OptionsGroupUI):
 
 
         self.setTitle(str(_("Gerber File associations")))
         self.setTitle(str(_("Gerber File associations")))
 
 
-        # ## Export G-Code
+        self.restore_btn = FCButton(_("Restore"))
+        self.restore_btn.setToolTip(_("Restore the extension list to the default state."))
+        self.del_all_btn = FCButton(_("Delete All"))
+        self.del_all_btn.setToolTip(_("Delete all extensions from the list."))
+
+        hlay0 = QtWidgets.QHBoxLayout()
+        self.layout.addLayout(hlay0)
+        hlay0.addWidget(self.restore_btn)
+        hlay0.addWidget(self.del_all_btn)
+
+        # ## Gerber associations
         self.grb_list_label = QtWidgets.QLabel("<b>%s:</b>" % _("Extensions list"))
         self.grb_list_label = QtWidgets.QLabel("<b>%s:</b>" % _("Extensions list"))
         self.grb_list_label.setToolTip(
         self.grb_list_label.setToolTip(
             _("List of file extensions to be\n"
             _("List of file extensions to be\n"
@@ -7873,13 +7956,33 @@ class FAGrbPrefGroupUI(OptionsGroupUI):
         self.layout.addWidget(self.grb_list_label)
         self.layout.addWidget(self.grb_list_label)
 
 
         self.grb_list_text = FCTextArea()
         self.grb_list_text = FCTextArea()
+        self.grb_list_text.setReadOnly(True)
         # self.grb_list_text.sizeHint(custom_sizehint=150)
         # self.grb_list_text.sizeHint(custom_sizehint=150)
         self.layout.addWidget(self.grb_list_text)
         self.layout.addWidget(self.grb_list_text)
         font = QtGui.QFont()
         font = QtGui.QFont()
         font.setPointSize(12)
         font.setPointSize(12)
         self.grb_list_text.setFont(font)
         self.grb_list_text.setFont(font)
 
 
-        self.grb_list_btn = FCButton(_("Apply"))
+        self.ext_label = QtWidgets.QLabel('%s:' % _("Extension"))
+        self.ext_label.setToolTip(_("A file extension to be added or deleted to the list."))
+        self.ext_entry = FCEntry()
+
+        hlay1 = QtWidgets.QHBoxLayout()
+        self.layout.addLayout(hlay1)
+        hlay1.addWidget(self.ext_label)
+        hlay1.addWidget(self.ext_entry)
+
+        self.add_btn = FCButton(_("Add Extension"))
+        self.add_btn.setToolTip(_("Add a file extension to the list"))
+        self.del_btn = FCButton(_("Delete Extension"))
+        self.del_btn.setToolTip(_("Delete a file extension from the list"))
+
+        hlay2 = QtWidgets.QHBoxLayout()
+        self.layout.addLayout(hlay2)
+        hlay2.addWidget(self.add_btn)
+        hlay2.addWidget(self.del_btn)
+
+        self.grb_list_btn = FCButton(_("Apply Association"))
         self.grb_list_btn.setToolTip(_("Apply the file associations between\n"
         self.grb_list_btn.setToolTip(_("Apply the file associations between\n"
                                        "FlatCAM and the files with above extensions.\n"
                                        "FlatCAM and the files with above extensions.\n"
                                        "They will be active after next logon.\n"
                                        "They will be active after next logon.\n"