diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 910ec373..b1ca9e15 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -1163,12 +1163,13 @@ class App(QtCore.QObject): "tools_sub_close_paths": True, # 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 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 self.ui.fa_defaults_form.fa_excellon_group.exc_list_btn.clicked.connect( 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 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.dxf_list = ['dxf'] self.pdf_list = ['pdf'] @@ -4582,19 +4615,19 @@ class App(QtCore.QObject): # register all keys in the Preferences window 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') # 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) + 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 - 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.")) if obj_type is None or obj_type == 'gcode': @@ -4603,19 +4636,19 @@ class App(QtCore.QObject): # register all keys in the Preferences window 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') # 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) + 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 - 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' % _("Selected GCode file extensions registered with FlatCAM.")) @@ -4625,22 +4658,116 @@ class App(QtCore.QObject): # register all keys in the Preferences window 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') # 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) + 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 - 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' % _("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): """ Callback for Edit->Join. Joins the selected geometry objects into diff --git a/README.md b/README.md index 238ca32c..723e6d40 100644 --- a/README.md +++ b/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 - added more programmers that contributed to FlatCAM over the years, in the "About FlatCAM" -> Programmers window diff --git a/flatcamEditors/FlatCAMGrbEditor.py b/flatcamEditors/FlatCAMGrbEditor.py index 1acddd2e..4b3efa48 100644 --- a/flatcamEditors/FlatCAMGrbEditor.py +++ b/flatcamEditors/FlatCAMGrbEditor.py @@ -3742,7 +3742,6 @@ class FlatCAMGrbEditor(QtCore.QObject): # temp_elem.append(deepcopy(new_elem)) for elem in self.gerber_obj.apertures[apid]['geometry']: new_elem = dict() - if 'solid' in elem: solid_geo = elem['solid'] for clear_geo in global_clear_geo: @@ -4434,16 +4433,18 @@ class FlatCAMGrbEditor(QtCore.QObject): self.plot_shape(geometry=geometric_data, color=self.app.defaults['global_sel_draw_color'], 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: 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() diff --git a/flatcamGUI/FlatCAMGUI.py b/flatcamGUI/FlatCAMGUI.py index 129714c1..c4a54b82 100644 --- a/flatcamGUI/FlatCAMGUI.py +++ b/flatcamGUI/FlatCAMGUI.py @@ -958,7 +958,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow): self.fa_tab = QtWidgets.QWidget() 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.setContentsMargins(2, 2, 2, 2) self.fa_tab.setLayout(self.fa_tab_lay) @@ -7794,34 +7794,77 @@ class ToolsSubPrefGroupUI(OptionsGroupUI): class FAExcPrefGroupUI(OptionsGroupUI): def __init__(self, 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"))) - # ## Export G-Code - self.exc_list_label = QtWidgets.QLabel("%s:" % _("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("%s:" % _("Extensions list")) + list_label.setToolTip( _("List of file extensions to be\n" "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.setReadOnly(True) # self.exc_list_text.sizeHint(custom_sizehint=150) font = QtGui.QFont() font.setPointSize(12) self.exc_list_text.setFont(font) - self.layout.addWidget(self.exc_list_text) + self.vertical_lay.addWidget(self.exc_list_text) - self.exc_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.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 Association")) self.exc_list_btn.setToolTip(_("Apply the file associations between\n" "FlatCAM and the files with above extensions.\n" "They will be active after next logon.\n" "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): @@ -7831,7 +7874,17 @@ class FAGcoPrefGroupUI(OptionsGroupUI): 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("%s:" % _("Extensions list")) self.gco_list_label.setToolTip( _("List of file extensions to be\n" @@ -7840,6 +7893,7 @@ class FAGcoPrefGroupUI(OptionsGroupUI): self.layout.addWidget(self.gco_list_label) self.gco_list_text = FCTextArea() + self.gco_list_text.setReadOnly(True) # self.gco_list_text.sizeHint(custom_sizehint=150) font = QtGui.QFont() font.setPointSize(12) @@ -7847,7 +7901,26 @@ class FAGcoPrefGroupUI(OptionsGroupUI): 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" "FlatCAM and the files with above extensions.\n" "They will be active after next logon.\n" @@ -7864,7 +7937,17 @@ class FAGrbPrefGroupUI(OptionsGroupUI): 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("%s:" % _("Extensions list")) self.grb_list_label.setToolTip( _("List of file extensions to be\n" @@ -7873,13 +7956,33 @@ class FAGrbPrefGroupUI(OptionsGroupUI): self.layout.addWidget(self.grb_list_label) self.grb_list_text = FCTextArea() + self.grb_list_text.setReadOnly(True) # self.grb_list_text.sizeHint(custom_sizehint=150) self.layout.addWidget(self.grb_list_text) font = QtGui.QFont() font.setPointSize(12) 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" "FlatCAM and the files with above extensions.\n" "They will be active after next logon.\n"