def create_default_config(self): # check for existing setting folder or create one self.make_settings_folder() # derive config file with defaults from spec self.var_dict = ConfigObj(configspec=CONFIG_SPEC) _vdt = Validator() self.var_dict.validate(_vdt, copy=True) self.var_dict.filename = self.filename self.var_dict.write()
def __init__(self): """ initialize the varspace of an existing plugin instance init_varspace() is a superclass method of plugin """ self.folder = os.path.join(g.folder, c.DEFAULT_CONFIG_DIR) self.filename = os.path.join(self.folder, 'config' + c.CONFIG_EXTENSION) self.default_config = False # whether a new name was generated self.var_dict = dict() self.spec = ConfigObj(CONFIG_SPEC, interpolation=False, list_values=False, _inspec=True) # try: self.load_config() # convenience - flatten nested config dict to access it via self.config.sectionname.varname self.vars = DictDotLookup(self.var_dict) self.mode3d = self.vars.General['mode3d'] self.machine_type = self.vars.General['machine_type'] self.fitting_tolerance = self.vars.Import_Parameters[ 'fitting_tolerance'] self.point_tolerance = self.vars.Import_Parameters['point_tolerance'] self.metric = 1 # true unit is determined while importing self.tool_units_metric = 0 if self.vars.General[ 'tool_units'] == 'in' else 1
def load_config(self): """Load Config File""" print(self.file_name) if os.path.isfile(self.file_name): try: # file exists, read & validate it self.var_dict = ConfigObj(self.file_name, configspec=CONFIG_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) except self.var_dict == None: #rw logger.error( "reading values from postprocessorconfig file error") #rw self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever
def create_default_config(self): """ If no postprocessor config file exists this function is called to generate the config file based on its specification. """ # check for existing setting folder or create one self.make_settings_folder() # derive config file with defaults from spec logger.debug(POSTPRO_SPEC) self.var_dict = ConfigObj(configspec=POSTPRO_SPEC) _vdt = Validator() self.var_dict.validate(_vdt, copy=True) self.var_dict.filename = self.filename self.var_dict.write()
def load_config(self): """ This method tries to load the defined postprocessor file given in self.file_name. If this fails it will create a new one """ try: # file exists, read & validate it self.var_dict = ConfigObj(self.file_name, configspec=POSTPRO_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) except self.var_dict == None: #rw logger.error("reading values from postprocessorconfig file error") #rw self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever self.update_config()
class MyPostProConfig(object): """ This class hosts all functions related to the PostProConfig File. """ def __init__(self, file_name='postpro_config' + c.CONFIG_EXTENSION): """ initialize the varspace of an existing plugin instance init_varspace() is a superclass method of plugin @param file_name: The file_name for the creation of a new config file and the file_name of the file to read config from. """ self.folder = os.path.join('C:\\PythonScripts\\1.Programming\\dxf2g\\config') self.file_name = os.path.join(self.folder, file_name) self.version_mismatch = '' # no problem for now self.default_config = False # whether a new name was generated self.var_dict = dict() self.spec = ConfigObj(POSTPRO_SPEC, interpolation=False, list_values=False, _inspec=True) def load_config(self): """ This method tries to load the defined postprocessor file given in self.file_name. If this fails it will create a new one """ try: # file exists, read & validate it self.var_dict = ConfigObj(self.file_name, configspec=POSTPRO_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) except self.var_dict == None: #rw logger.error("reading values from postprocessorconfig file error") #rw self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever self.update_config() def update_config(self): """ Call this function each time the self.var_dict is updated (eg when the postprocessor configuration window changes some settings) """ # convenience - flatten nested config dict to access it via self.config.sectionname.varname self.vars = DictDotLookup(self.var_dict) # add here any update needed for the internal variables of this class def make_settings_folder(self): """ This method creates the postprocessor settings folder if necessary """ try: os.mkdir(self.folder) except OSError: pass
def __init__(self, file_name='postpro_config' + c.CONFIG_EXTENSION): """ initialize the varspace of an existing plugin instance init_varspace() is a superclass method of plugin @param file_name: The file_name for the creation of a new config file and the file_name of the file to read config from. """ self.folder = os.path.join('C:\\PythonScripts\\1.Programming\\dxf2g\\config') self.file_name = os.path.join(self.folder, file_name) self.version_mismatch = '' # no problem for now self.default_config = False # whether a new name was generated self.var_dict = dict() self.spec = ConfigObj(POSTPRO_SPEC, interpolation=False, list_values=False, _inspec=True)
def __init__(self, filename='postpro_config' + c.CONFIG_EXTENSION): """ initialize the varspace of an existing plugin instance init_varspace() is a superclass method of plugin @param filename: The filename for the creation of a new config file and the filename of the file to read config from. """ self.folder = os.path.join(g.folder, c.DEFAULT_POSTPRO_DIR) self.filename = os.path.join(self.folder, filename) self.default_config = False # whether a new name was generated self.var_dict = dict() self.spec = ConfigObj(POSTPRO_SPEC, interpolation=False, list_values=False, _inspec=True)
def __init__(self, script_dir): """ initialize the varspace of an existing plugin instance init_varspace() is a superclass method of plugin """ self.folder = script_dir + '\\config' self.file_name = os.path.join(self.folder, 'config' + c.CONFIG_EXTENSION) self.version_mismatch = '' # no problem for now self.default_config = False # whether a new name was generated self.var_dict = dict() self.spec = ConfigObj(CONFIG_SPEC, interpolation=False, list_values=False, _inspec=True) # try: self.load_config() self.update_config() # The following settings won't be modified after a change in the configuration window. # If a setting need to be updated when the configuration changes, move it to the update_config() function self.mode3d = self.vars.General['mode3d'] self.machine_type = self.vars.General['machine_type'] self.fitting_tolerance = self.vars.Import_Parameters[ 'fitting_tolerance'] self.point_tolerance = self.vars.Import_Parameters['point_tolerance'] self.metric = 1 # true unit is determined while importing self.tool_units = self.vars.General[ 'tool_units'] # store the initial tool_units (we don't want it to change until software restart) self.tool_units_metric = 0 if self.vars.General[ 'tool_units'] == 'in' else 1
class MyConfig(object): """ This class hosts all functions related to the Config File. """ def __init__(self): """ initialize the varspace of an existing plugin instance init_varspace() is a superclass method of plugin """ self.folder = os.path.join(g.folder, c.DEFAULT_CONFIG_DIR) self.filename = os.path.join(self.folder, 'config' + c.CONFIG_EXTENSION) self.version_mismatch = '' # no problem for now self.default_config = False # whether a new name was generated self.var_dict = dict() self.spec = ConfigObj(CONFIG_SPEC, interpolation=False, list_values=False, _inspec=True) # try: self.load_config() self.update_config() # The following settings won't be modified after a change in the configuration window. # If a setting need to be updated when the configuration changes, move it to the update_config() function self.mode3d = self.vars.General['mode3d'] self.machine_type = self.vars.General['machine_type'] self.fitting_tolerance = self.vars.Import_Parameters['fitting_tolerance'] self.point_tolerance = self.vars.Import_Parameters['point_tolerance'] self.metric = 1 # true unit is determined while importing self.tool_units = self.vars.General['tool_units'] # store the initial tool_units (we don't want it to change until software restart) self.tool_units_metric = 0 if self.vars.General['tool_units'] == 'in' else 1 # except Exception, msg: # logger.warning(self.tr("Config loading failed: %s") % msg) # return False def tr(self, string_to_translate): """ Translate a string using the QCoreApplication translation framework @param string_to_translate: a unicode string @return: the translated unicode string if it was possible to translate """ return text_type(QtCore.QCoreApplication.translate('MyConfig', string_to_translate)) def update_config(self): """ Call this function each time the self.var_dict is updated (eg when the configuration window changes some settings) """ # convenience - flatten nested config dict to access it via self.config.sectionname.varname self.vars = DictDotLookup(self.var_dict) # add here any update needed for the internal variables of this class def make_settings_folder(self): """Create settings folder if necessary""" try: os.mkdir(self.folder) except OSError: pass def load_config(self): """Load Config File""" if os.path.isfile(self.filename): try: # file exists, read & validate it self.var_dict = ConfigObj(self.filename, configspec=CONFIG_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) if validate_errors: logger.error(self.tr("errors reading %s:") % self.filename) for entry in validate_errors: section_list, key, error = entry if key is not None: section_list.append(key) else: section_list.append('[missing section]') section_string = ', '.join(section_list) if not error: error = self.tr('Missing value or section.') logger.error(section_string + ' = ' + error) if validate_errors: raise BadConfigFileError("syntax errors in config file") # check config file version against internal version if CONFIG_VERSION: fileversion = self.var_dict['Version']['config_version'] # this could raise KeyError if fileversion != CONFIG_VERSION: raise VersionMismatchError(fileversion, CONFIG_VERSION) except VersionMismatchError: #raise VersionMismatchError(fileversion, CONFIG_VERSION) # version mismatch flag, it will be used to display an error. self.version_mismatch = self.tr("The configuration file version ({0}) doesn't match the software expected version ({1}).\n\nYou have to delete (or carefully edit) the configuration file \"{2}\" to solve the problem.").format(fileversion, CONFIG_VERSION, self.filename) except Exception as inst: logger.error(inst) (base, ext) = os.path.splitext(self.filename) badfilename = base + c.BAD_CONFIG_EXTENSION logger.debug(self.tr("trying to rename bad cfg %s to %s") % (self.filename, badfilename)) try: os.rename(self.filename, badfilename) except OSError as e: logger.error(self.tr("rename(%s,%s) failed: %s") % (self.filename, badfilename, e.strerror)) raise else: logger.debug(self.tr("renamed bad varspace %s to '%s'") % (self.filename, badfilename)) self.create_default_config() self.default_config = True logger.debug(self.tr("created default varspace '%s'") % self.filename) else: self.default_config = False # logger.debug(self.dir()) # logger.debug(self.tr("created default varspace '%s'") % self.filename) # logger.debug(self.tr("read existing varspace '%s'") % self.filename) else: self.create_default_config() self.default_config = True logger.debug(self.tr("created default varspace '%s'") % self.filename) self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever def create_default_config(self): # check for existing setting folder or create one self.make_settings_folder() # derive config file with defaults from spec self.var_dict = ConfigObj(configspec=CONFIG_SPEC) _vdt = Validator() self.var_dict.validate(_vdt, copy=True) self.var_dict.filename = self.filename self.var_dict.write() def _save_varspace(self): """Saves Variables space""" self.var_dict.filename = self.filename self.var_dict.write() def print_vars(self): """Prints Variables""" print("Variables:") for k, v in self.var_dict['Variables'].items(): print(k, "=", v) def makeConfigWindgets(self): """ Build the configuration widgets and store them into a dictionary. The structure of the dictionnary must match the structure of the configuration file. The names of the keys must be identical to those used in the configfile. If a name is declared in the configfile but not here, it simply won't appear in the config window (the config_version for example must not be modified by the user, so it is not declared here) """ self.cfg_widget_def = \ { '__section_title__': { # This section is only used for assigning titles to the keys of the dictionnary (= name of the sections used in the config file). # This name is displayed in the tabs of the configuration window ; if no name is provided, the key name is used. A same title may be used for several keys : in this case, all the items that belongs to this section are regrouped into the same tab. # Note: the title may be specified in the section itselt too, using special entry "'__section_title__': Title to use" 'Tool_Parameters': self.tr("Tools table"), 'Custom_Actions' : self.tr("Custom actions"), }, 'Paths': { '__section_title__': self.tr("Software config"), 'import_dir': CfgLineEdit(self.tr('Default look for DXF files in:')), 'output_dir': CfgLineEdit(self.tr('Default export generated GCODE to:')), }, 'Filters': { '__section_title__': self.tr("Software config"), 'pstoedit_cmd': CfgLineEdit(self.tr('pstoedit command location:')), 'pstoedit_opt': CfgListEdit(self.tr('pstoedit options:'), ','), }, 'Axis_letters': { '__section_title__': self.tr("Machine config"), 'ax1_letter': CfgLineEdit(self.tr('Letter used for first axis:')), 'ax2_letter': CfgLineEdit(self.tr('Letter used for second axis:')), 'ax3_letter': CfgLineEdit(self.tr('Letter used for third axis:')), }, 'Plane_Coordinates': { '__section_title__': self.tr("Machine config"), 'axis1_start_end': CfgDoubleSpinBox(self.tr('Start/End coordinate for first axis:')), 'axis2_start_end': CfgDoubleSpinBox(self.tr('Start/End coordinate for second axis:')), }, 'Depth_Coordinates': { '__section_title__': self.tr("Machine config"), 'axis3_retract': CfgDoubleSpinBox(self.tr('Third axis default retraction coordinate:')), 'axis3_safe_margin': CfgDoubleSpinBox(self.tr('Third axis default safe coordinate:')), 'axis3_start_mill_depth': CfgDoubleSpinBox(self.tr('Third axis default workpiece origin:')), 'axis3_slice_depth': CfgDoubleSpinBox(self.tr('Third axis default slice depth:')), 'axis3_mill_depth': CfgDoubleSpinBox(self.tr('Third axis default final mill depth:')), }, 'Feed_Rates': { '__section_title__': self.tr("Machine config"), 'f_g1_plane': CfgDoubleSpinBox(self.tr('G1 feed rate for first and second axis (2D plane):'), ' mm/min'), 'f_g1_depth': CfgDoubleSpinBox(self.tr('G1 feed rate for third axis:'), ' mm/min'), }, 'General': { '__section_title__': self.tr("Software config"), 'mode3d': CfgCheckBox(self.tr('3D mode (requires OpenGL - Needs a software restart)')), 'write_to_stdout': CfgCheckBox(self.tr('Export GCODE to stdout (instead of a file)')), 'show_disabled_paths': CfgCheckBox(self.tr('Default enable "Show Disabled Paths"')), 'live_update_export_route': CfgCheckBox(self.tr('Default enable "Live Update Export Route"')), 'split_line_segments': CfgCheckBox(self.tr('Default enable "Split Line Segments" (create tabs on last slices)')), 'automatic_cutter_compensation': CfgCheckBox(self.tr('Default enable "Automatic Cutter Compensation"')), 'machine_type': CfgComboBox(self.tr('Default machine type at startup:')), 'tool_units': CfgComboBox(self.tr('Units for tools (needs a software restart):')), #'test': #{ # 'test_niveau_2': CfgCheckBox('Pour test'), # 'test2_niveau_2': CfgComboBox('Pour test', ('milling', 'lathe', 'drag_knife'), 'milling'), #}, }, 'Cutter_Compensation': { '__section_title__': self.tr("Output settings"), 'done_by_machine': CfgCheckBox(self.tr('Cutter compensation is done by machine (check this box if the machine reconizes G41 and G42 commands / uncheck it otherwise)')), }, 'Drag_Knife_Options': { 'drag_angle': CfgDoubleSpinBox(self.tr('Angle above which the tool retracts to slice depth (see "Third axis slice depth parameter"):'), u'°'), #u for unicode }, 'Route_Optimisation': { '__section_title__': self.tr("Output settings"), 'default_TSP': CfgCheckBox(self.tr('Default enable the TSP output path optimisation for each shape (TSP = Travelling Salesman Problem method)')), 'TSP_shape_order': CfgComboBox(self.tr('"Constrain order only" mixes fixed and optimized shapes\n"Constrain place after" always place optimized shapes after fixed shapes:')), 'mutation_rate': CfgDoubleSpinBox(self.tr('Mutation rate for TSP optimizer:')), 'max_population': CfgSpinBox(self.tr('Max population for the TSP optimizer:')), 'max_iterations': CfgSpinBox(self.tr('Max iterations for the TSP optimizer:')), 'begin_art': CfgComboBox(self.tr('TSP start method:')), }, 'Import_Parameters': { '__section_title__': self.tr("Output settings"), 'point_tolerance': CfgDoubleSpinBox(self.tr('DXF default import point tolerance:'), '', None, None, 5), 'spline_check': CfgSpinBox(self.tr('DXF import spline check:')), 'fitting_tolerance': CfgDoubleSpinBox(self.tr('DXF default import fit tolerance:'), '', None, None, 5), 'insert_at_block_layer': CfgCheckBox(self.tr('insert elements which are part of a block to layer where the block is inserted')), }, 'Layer_Options': { '__section_title__': self.tr("Automatic tool config"), 'id_float_separator': CfgLineEdit(self.tr('Separator between identifier and value:')), 'mill_depth_identifiers': CfgListEdit(self.tr('Identifiers that can be used for Final mill depth:'), ','), 'slice_depth_identifiers': CfgListEdit(self.tr('Identifiers that can be used for Infeed depth:'), ','), 'start_mill_depth_identifiers': CfgListEdit(self.tr('Identifiers that can be used for Workpiece top:'), ','), 'retract_identifiers': CfgListEdit(self.tr('Identifiers that can be used for Z Retraction area:'), ','), 'safe_margin_identifiers': CfgListEdit(self.tr('Identifiers that can be used for Z Safety margin:'), ','), 'f_g1_plane_identifiers': CfgListEdit(self.tr('Identifiers that can be used for G1 feed rate of XY plane:'), ','), 'f_g1_depth_identifiers': CfgListEdit(self.tr('Identifiers that can be used for G1 feed rate of Z:'), ','), 'tool_nr_identifiers': CfgListEdit(self.tr('Identifiers that can be used for tool number selection:'), ','), 'tool_diameter_identifiers': CfgListEdit(self.tr('Identifiers that can be used for tool diameter setting:'), ','), 'spindle_speed_identifiers': CfgListEdit(self.tr('Identifiers that can be used for spindle speed:'), ','), 'start_radius_identifiers': CfgListEdit(self.tr('Identifiers that can be used for start radius:'), ','), }, 'Tool_Parameters': CfgTableToolParameters(self.tr('Define the tools here:')), 'Custom_Actions': CfgTableCustomActions(self.tr('Define here custom GCODE that can be inserted anywhere in the program:')), 'Logging': { '__section_title__': self.tr("Software config"), 'logfile': CfgLineEdit(self.tr('File used for logging (software restart needed):')), 'console_loglevel': CfgComboBox(self.tr('Log any message with importance >= to log level on stderr console (software restart needed):')), 'file_loglevel': CfgComboBox(self.tr('Log any message with importance >= to log level in logfile (software restart needed):')), 'window_loglevel': CfgComboBox(self.tr('Log any message with importance >= to log level on the message window (software restart needed):')), }, } return self.cfg_widget_def
def load_config(self): """ This method tries to load the defined postprocessor file given in self.filename. If this fails it will create a new one """ try: # file exists, read & validate it self.var_dict = ConfigObj(self.filename, configspec=POSTPRO_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) if validate_errors: g.logger.logger.error( self.tr("errors reading %s:") % self.filename) for entry in validate_errors: section_list, key, error = entry if key is not None: section_list.append(key) else: section_list.append('[missing section]') section_string = ', '.join(section_list) if error == False: error = self.tr('Missing value or section.') g.logger.logger.error(section_string + ' = ' + error) if validate_errors: raise BadConfigFileError( self.tr("syntax errors in postpro_config file")) # check config file version against internal version if POSTPRO_VERSION: fileversion = self.var_dict['Version'][ 'config_version'] # this could raise KeyError if fileversion != POSTPRO_VERSION: raise VersionMismatchError(fileversion, POSTPRO_VERSION) except VersionMismatchError: raise VersionMismatchError(fileversion, POSTPRO_VERSION) except Exception as inst: logger.error(inst) (base, ext) = os.path.splitext(self.filename) badfilename = base + c.BAD_CONFIG_EXTENSION logger.debug( self.tr("trying to rename bad cfg %s to %s") % (self.filename, badfilename)) try: os.rename(self.filename, badfilename) except OSError as e: logger.error( self.tr("rename(%s,%s) failed: %s") % (self.filename, badfilename, e.strerror)) raise else: logger.debug( self.tr("renamed bad varspace %s to '%s'") % (self.filename, badfilename)) self.create_default_config() self.default_config = True logger.debug( self.tr("created default varspace '%s'") % self.filename) else: self.default_config = False logger.debug( self.tr("read existing varspace '%s'") % self.filename) # convenience - flatten nested config dict to access it via self.config.sectionname.varname self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever self.vars = DictDotLookup(self.var_dict)
class MyPostProConfig(object): """ This class hosts all functions related to the PostProConfig File. """ def __init__(self, filename='postpro_config' + c.CONFIG_EXTENSION): """ initialize the varspace of an existing plugin instance init_varspace() is a superclass method of plugin @param filename: The filename for the creation of a new config file and the filename of the file to read config from. """ self.folder = os.path.join(g.folder, c.DEFAULT_POSTPRO_DIR) self.filename = os.path.join(self.folder, filename) self.default_config = False # whether a new name was generated self.var_dict = dict() self.spec = ConfigObj(POSTPRO_SPEC, interpolation=False, list_values=False, _inspec=True) def tr(self, string_to_translate): """ Translate a string using the QCoreApplication translation framework @param: string_to_translate: a unicode string @return: the translated unicode string if it was possible to translate """ return text_type( QtCore.QCoreApplication.translate("MyPostProConfig", string_to_translate)) def load_config(self): """ This method tries to load the defined postprocessor file given in self.filename. If this fails it will create a new one """ try: # file exists, read & validate it self.var_dict = ConfigObj(self.filename, configspec=POSTPRO_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) if validate_errors: g.logger.logger.error( self.tr("errors reading %s:") % self.filename) for entry in validate_errors: section_list, key, error = entry if key is not None: section_list.append(key) else: section_list.append('[missing section]') section_string = ', '.join(section_list) if error == False: error = self.tr('Missing value or section.') g.logger.logger.error(section_string + ' = ' + error) if validate_errors: raise BadConfigFileError( self.tr("syntax errors in postpro_config file")) # check config file version against internal version if POSTPRO_VERSION: fileversion = self.var_dict['Version'][ 'config_version'] # this could raise KeyError if fileversion != POSTPRO_VERSION: raise VersionMismatchError(fileversion, POSTPRO_VERSION) except VersionMismatchError: raise VersionMismatchError(fileversion, POSTPRO_VERSION) except Exception as inst: logger.error(inst) (base, ext) = os.path.splitext(self.filename) badfilename = base + c.BAD_CONFIG_EXTENSION logger.debug( self.tr("trying to rename bad cfg %s to %s") % (self.filename, badfilename)) try: os.rename(self.filename, badfilename) except OSError as e: logger.error( self.tr("rename(%s,%s) failed: %s") % (self.filename, badfilename, e.strerror)) raise else: logger.debug( self.tr("renamed bad varspace %s to '%s'") % (self.filename, badfilename)) self.create_default_config() self.default_config = True logger.debug( self.tr("created default varspace '%s'") % self.filename) else: self.default_config = False logger.debug( self.tr("read existing varspace '%s'") % self.filename) # convenience - flatten nested config dict to access it via self.config.sectionname.varname self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever self.vars = DictDotLookup(self.var_dict) def make_settings_folder(self): """ This method creates the postprocessor settings folder if necessary """ try: os.mkdir(self.folder) except OSError: pass def create_default_config(self): """ If no postprocessor config file exists this function is called to generate the config file based on its specification. """ # check for existing setting folder or create one self.make_settings_folder() # derive config file with defaults from spec logger.debug(POSTPRO_SPEC) self.var_dict = ConfigObj(configspec=POSTPRO_SPEC) _vdt = Validator() self.var_dict.validate(_vdt, copy=True) self.var_dict.filename = self.filename self.var_dict.write() # def _save_varspace(self): # self.var_dict.filename = self.filename # self.var_dict.write() # def print_vars(self): """ Print all the variables with their values """ print("Variables:") for k, v in self.var_dict['Variables'].items(): print(k, "=", v)
def load_config(self): """Load Config File""" if os.path.isfile(self.filename): try: # file exists, read & validate it self.var_dict = ConfigObj(self.filename, configspec=CONFIG_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) if validate_errors: logger.error(self.tr("errors reading %s:") % self.filename) for entry in validate_errors: section_list, key, error = entry if key is not None: section_list.append(key) else: section_list.append('[missing section]') section_string = ', '.join(section_list) if not error: error = self.tr('Missing value or section.') logger.error(section_string + ' = ' + error) if validate_errors: raise BadConfigFileError("syntax errors in config file") # check config file version against internal version if CONFIG_VERSION: fileversion = self.var_dict['Version'][ 'config_version'] # this could raise KeyError if fileversion != CONFIG_VERSION: raise VersionMismatchError(fileversion, CONFIG_VERSION) except VersionMismatchError: #raise VersionMismatchError(fileversion, CONFIG_VERSION) # version mismatch flag, it will be used to display an error. self.version_mismatch = self.tr( "The configuration file version ({0}) doesn't match the software expected version ({1}).\n\nYou have to delete (or carefully edit) the configuration file \"{2}\" to solve the problem." ).format(fileversion, CONFIG_VERSION, self.filename) except Exception as inst: logger.error(inst) (base, ext) = os.path.splitext(self.filename) badfilename = base + c.BAD_CONFIG_EXTENSION logger.debug( self.tr("trying to rename bad cfg %s to %s") % (self.filename, badfilename)) try: os.rename(self.filename, badfilename) except OSError as e: logger.error( self.tr("rename(%s,%s) failed: %s") % (self.filename, badfilename, e.strerror)) raise else: logger.debug( self.tr("renamed bad varspace %s to '%s'") % (self.filename, badfilename)) self.create_default_config() self.default_config = True logger.debug( self.tr("created default varspace '%s'") % self.filename) else: self.default_config = False # logger.debug(self.dir()) # logger.debug(self.tr("created default varspace '%s'") % self.filename) # logger.debug(self.tr("read existing varspace '%s'") % self.filename) else: self.create_default_config() self.default_config = True logger.debug( self.tr("created default varspace '%s'") % self.filename) self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever
class MyPostProConfig(object): """ This class hosts all functions related to the PostProConfig File. """ def __init__(self, filename='postpro_config' + c.CONFIG_EXTENSION): """ initialize the varspace of an existing plugin instance init_varspace() is a superclass method of plugin @param filename: The filename for the creation of a new config file and the filename of the file to read config from. """ self.folder = os.path.join(g.folder, c.DEFAULT_POSTPRO_DIR) self.filename = os.path.join(self.folder, filename) self.version_mismatch = '' # no problem for now self.default_config = False # whether a new name was generated self.var_dict = dict() self.spec = ConfigObj(POSTPRO_SPEC, interpolation=False, list_values=False, _inspec=True) def load_config(self): """ This method tries to load the defined postprocessor file given in self.filename. If this fails it will create a new one """ try: # file exists, read & validate it self.var_dict = ConfigObj(self.filename, configspec=POSTPRO_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) if validate_errors: logger.error(self.tr("errors reading %s:") % self.filename) for entry in validate_errors: section_list, key, error = entry if key is not None: section_list.append(key) else: section_list.append('[missing section]') section_string = ', '.join(section_list) if error == False: error = self.tr('Missing value or section.') logger.error(section_string + ' = ' + error) if validate_errors: raise BadConfigFileError( self.tr("syntax errors in postpro_config file")) # check config file version against internal version if POSTPRO_VERSION: fileversion = self.var_dict['Version'][ 'config_version'] # this could raise KeyError if fileversion != POSTPRO_VERSION: raise VersionMismatchError(fileversion, POSTPRO_VERSION) except VersionMismatchError: # version mismatch flag, it will be used to display an error. self.version_mismatch = self.tr( "The postprocessor configuration file version ({0}) doesn't match the software expected version ({1}).\n\nYou have to delete (or carefully edit) the configuration file \"{2}\" to solve the problem." ).format(fileversion, POSTPRO_VERSION, self.filename) except Exception as inst: #logger.error(inst) (base, ext) = os.path.splitext(self.filename) badfilename = base + c.BAD_CONFIG_EXTENSION logger.debug( self.tr("trying to rename bad cfg %s to %s") % (self.filename, badfilename)) try: os.rename(self.filename, badfilename) except OSError as e: logger.error( self.tr("rename(%s,%s) failed: %s") % (self.filename, badfilename, e.strerror)) raise else: logger.debug( self.tr("renamed bad varspace %s to '%s'") % (self.filename, badfilename)) self.create_default_config() self.default_config = True logger.debug( self.tr("created default varspace '%s'") % self.filename) else: self.default_config = False logger.debug( self.tr("read existing varspace '%s'") % self.filename) # convenience - flatten nested config dict to access it via self.config.sectionname.varname self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever self.update_config() def update_config(self): """ Call this function each time the self.var_dict is updated (eg when the postprocessor configuration window changes some settings) """ # convenience - flatten nested config dict to access it via self.config.sectionname.varname # print self.var_dict; self.vars = DictDotLookup(self.var_dict) # print self.vars.General["abs_export"]; # add here any update needed for the internal variables of this class def make_settings_folder(self): """ This method creates the postprocessor settings folder if necessary """ try: os.mkdir(self.folder) except OSError: pass def create_default_config(self): """ If no postprocessor config file exists this function is called to generate the config file based on its specification. """ # check for existing setting folder or create one self.make_settings_folder() # derive config file with defaults from spec logger.debug(POSTPRO_SPEC) self.var_dict = ConfigObj(configspec=POSTPRO_SPEC) _vdt = Validator() self.var_dict.validate(_vdt, copy=True) self.var_dict.filename = self.filename self.var_dict.write() def save_varspace(self): self.var_dict.filename = self.filename self.var_dict.write() def print_vars(self): """ Print all the variables with their values """ print("Variables:") for k, v in self.var_dict['Variables'].items(): print(k, "=", v) @staticmethod def tr(string_to_translate): """ Translate a string using the QCoreApplication translation framework @param string_to_translate: a unicode string @return: the translated unicode string if it was possible to translate """ return text_type(string_to_translate) @staticmethod def makeConfigWidgets(): """ Build the postprocessor configuration widgets and store them into a dictionary. The structure of the dictionnary must match the structure of the postprocessor configuration file. The names of the keys must be identical to those used in the configfile. If a name is declared in the configfile but not here, it simply won't appear in the config window (the config_version for example must not be modified by the user, so it is not declared here) """ cfg_widget_def = OrderedDict([]) return cfg_widget_def
class MyConfig(object): """ This class hosts all functions related to the Config File. """ def __init__(self): """ initialize the varspace of an existing plugin instance init_varspace() is a superclass method of plugin """ self.folder = os.path.join(g.folder, c.DEFAULT_CONFIG_DIR) self.filename = os.path.join(self.folder, 'config' + c.CONFIG_EXTENSION) self.default_config = False # whether a new name was generated self.var_dict = dict() self.spec = ConfigObj(CONFIG_SPEC, interpolation=False, list_values=False, _inspec=True) # try: self.load_config() # convenience - flatten nested config dict to access it via self.config.sectionname.varname self.vars = DictDotLookup(self.var_dict) self.mode3d = self.vars.General['mode3d'] self.machine_type = self.vars.General['machine_type'] self.fitting_tolerance = self.vars.Import_Parameters[ 'fitting_tolerance'] self.point_tolerance = self.vars.Import_Parameters['point_tolerance'] self.metric = 1 # true unit is determined while importing self.tool_units_metric = 0 if self.vars.General[ 'tool_units'] == 'in' else 1 # except Exception, msg: # logger.warning(self.tr("Config loading failed: %s") % msg) # return False def tr(self, string_to_translate): """ Translate a string using the QCoreApplication translation framework @param string_to_translate: a unicode string @return: the translated unicode string if it was possible to translate """ return text_type( QtCore.QCoreApplication.translate('MyConfig', string_to_translate)) def make_settings_folder(self): """Create settings folder if necessary""" try: os.mkdir(self.folder) except OSError: pass def load_config(self): """Load Config File""" if os.path.isfile(self.filename): try: # file exists, read & validate it self.var_dict = ConfigObj(self.filename, configspec=CONFIG_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) if validate_errors: logger.error(self.tr("errors reading %s:") % self.filename) for entry in validate_errors: section_list, key, error = entry if key is not None: section_list.append(key) else: section_list.append('[missing section]') section_string = ', '.join(section_list) if not error: error = self.tr('Missing value or section.') logger.error(section_string + ' = ' + error) if validate_errors: raise BadConfigFileError("syntax errors in config file") # check config file version against internal version if CONFIG_VERSION: fileversion = self.var_dict['Version'][ 'config_version'] # this could raise KeyError if fileversion != CONFIG_VERSION: raise VersionMismatchError(fileversion, CONFIG_VERSION) except VersionMismatchError: raise VersionMismatchError( fileversion, CONFIG_VERSION) # TODO pop-up error? except Exception as inst: logger.error(inst) (base, ext) = os.path.splitext(self.filename) badfilename = base + c.BAD_CONFIG_EXTENSION logger.debug( self.tr("trying to rename bad cfg %s to %s") % (self.filename, badfilename)) try: os.rename(self.filename, badfilename) except OSError as e: logger.error( self.tr("rename(%s,%s) failed: %s") % (self.filename, badfilename, e.strerror)) raise else: logger.debug( self.tr("renamed bad varspace %s to '%s'") % (self.filename, badfilename)) self.create_default_config() self.default_config = True logger.debug( self.tr("created default varspace '%s'") % self.filename) else: self.default_config = False # logger.debug(self.dir()) # logger.debug(self.tr("created default varspace '%s'") % self.filename) # logger.debug(self.tr("read existing varspace '%s'") % self.filename) else: self.create_default_config() self.default_config = True logger.debug( self.tr("created default varspace '%s'") % self.filename) self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever def create_default_config(self): # check for existing setting folder or create one self.make_settings_folder() # derive config file with defaults from spec self.var_dict = ConfigObj(configspec=CONFIG_SPEC) _vdt = Validator() self.var_dict.validate(_vdt, copy=True) self.var_dict.filename = self.filename self.var_dict.write() def _save_varspace(self): """Saves Variables space""" self.var_dict.filename = self.filename self.var_dict.write() def print_vars(self): """Prints Variables""" print("Variables:") for k, v in self.var_dict['Variables'].items(): print(k, "=", v)
class MyConfig(object): """ This class hosts all functions related to the Config File. """ def __init__(self): """ initialize the varspace of an existing plugin instance init_varspace() is a superclass method of plugin """ self.folder = os.path.join(g.folder, c.DEFAULT_CONFIG_DIR) self.filename = os.path.join(self.folder, 'config' + c.CONFIG_EXTENSION) self.version_mismatch = '' # no problem for now self.default_config = False # whether a new name was generated self.var_dict = dict() self.spec = ConfigObj(CONFIG_SPEC, interpolation=False, list_values=False, _inspec=True) # try: self.load_config() self.update_config() # The following settings won't be modified after a change in the configuration window. # If a setting need to be updated when the configuration changes, move it to the update_config() function self.machine_type = self.vars.General['machine_type'] self.fitting_tolerance = self.vars.Import_Parameters[ 'fitting_tolerance'] self.point_tolerance = self.vars.Import_Parameters['point_tolerance'] self.metric = 1 # true unit is determined while importing self.tool_units = self.vars.General[ 'tool_units'] # store the initial tool_units (we don't want it to change until software restart) self.tool_units_metric = 0 if self.vars.General[ 'tool_units'] == 'in' else 1 # except Exception, msg: # logger.warning(self.tr("Config loading failed: %s") % msg) # return False def tr(self, string_to_translate): """ Translate a string using the QCoreApplication translation framework @param string_to_translate: a unicode string @return: the translated unicode string if it was possible to translate """ return text_type(string_to_translate) def update_config(self): """ Call this function each time the self.var_dict is updated (eg when the configuration window changes some settings) """ # convenience - flatten nested config dict to access it via self.config.sectionname.varname self.vars = DictDotLookup(self.var_dict) # add here any update needed for the internal variables of this class def make_settings_folder(self): """Create settings folder if necessary""" try: os.mkdir(self.folder) except OSError: pass def load_config(self): """Load Config File""" if os.path.isfile(self.filename): try: # file exists, read & validate it self.var_dict = ConfigObj(self.filename, configspec=CONFIG_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) if validate_errors: logger.error(self.tr("errors reading %s:") % self.filename) for entry in validate_errors: section_list, key, error = entry if key is not None: section_list.append(key) else: section_list.append('[missing section]') section_string = ', '.join(section_list) if not error: error = self.tr('Missing value or section.') logger.error(section_string + ' = ' + error) if validate_errors: raise BadConfigFileError("syntax errors in config file") # check config file version against internal version if CONFIG_VERSION: fileversion = self.var_dict['Version'][ 'config_version'] # this could raise KeyError if fileversion != CONFIG_VERSION: raise VersionMismatchError(fileversion, CONFIG_VERSION) except VersionMismatchError: #raise VersionMismatchError(fileversion, CONFIG_VERSION) # version mismatch flag, it will be used to display an error. self.version_mismatch = self.tr( "The configuration file version ({0}) doesn't match the software expected version ({1}).\n\nYou have to delete (or carefully edit) the configuration file \"{2}\" to solve the problem." ).format(fileversion, CONFIG_VERSION, self.filename) except Exception as inst: logger.error(inst) (base, ext) = os.path.splitext(self.filename) badfilename = base + c.BAD_CONFIG_EXTENSION logger.debug( self.tr("trying to rename bad cfg %s to %s") % (self.filename, badfilename)) try: os.rename(self.filename, badfilename) except OSError as e: logger.error( self.tr("rename(%s,%s) failed: %s") % (self.filename, badfilename, e.strerror)) raise else: logger.debug( self.tr("renamed bad varspace %s to '%s'") % (self.filename, badfilename)) self.create_default_config() self.default_config = True logger.debug( self.tr("created default varspace '%s'") % self.filename) else: self.default_config = False # logger.debug(self.dir()) # logger.debug(self.tr("created default varspace '%s'") % self.filename) # logger.debug(self.tr("read existing varspace '%s'") % self.filename) else: self.create_default_config() self.default_config = True logger.debug( self.tr("created default varspace '%s'") % self.filename) self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever def create_default_config(self): # check for existing setting folder or create one self.make_settings_folder() # derive config file with defaults from spec self.var_dict = ConfigObj(configspec=CONFIG_SPEC) _vdt = Validator() self.var_dict.validate(_vdt, copy=True) self.var_dict.filename = self.filename self.var_dict.write() def save_varspace(self): """Saves Variables space""" self.var_dict.filename = self.filename self.var_dict.write() def print_vars(self): """Prints Variables""" print("Variables:") for k, v in self.var_dict['Variables'].items(): print(k, "=", v) def makeConfigWidgets(self): """ Build the configuration widgets and store them into a dictionary. The structure of the dictionnary must match the structure of the configuration file. The names of the keys must be identical to those used in the configfile. If a name is declared in the configfile but not here, it simply won't appear in the config window (the config_version for example must not be modified by the user, so it is not declared here) """ coordinate_unit = self.tr( " mm") if self.tool_units_metric else self.tr(" in") speed_unit = self.tr(" mm/min") if self.tool_units_metric else self.tr( " IPS") cfg_widget_def = OrderedDict([]) return cfg_widget_def
def load_config(self): """ This method tries to load the defined postprocessor file given in self.filename. If this fails it will create a new one """ try: # file exists, read & validate it self.var_dict = ConfigObj(self.filename, configspec=POSTPRO_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) if validate_errors: g.logger.logger.error(self.tr("errors reading %s:") % self.filename) for entry in validate_errors: section_list, key, error = entry if key is not None: section_list.append(key) else: section_list.append('[missing section]') section_string = ', '.join(section_list) if error == False: error = self.tr('Missing value or section.') g.logger.logger.error( section_string + ' = ' + error) if validate_errors: raise BadConfigFileError(self.tr("syntax errors in postpro_config file")) # check config file version against internal version if POSTPRO_VERSION: fileversion = self.var_dict['Version']['config_version'] # this could raise KeyError if fileversion != POSTPRO_VERSION: raise VersionMismatchError(fileversion, POSTPRO_VERSION) except VersionMismatchError: raise VersionMismatchError(fileversion, POSTPRO_VERSION) except Exception as inst: logger.error(inst) (base, ext) = os.path.splitext(self.filename) badfilename = base + c.BAD_CONFIG_EXTENSION logger.debug(self.tr("trying to rename bad cfg %s to %s") % (self.filename, badfilename)) try: os.rename(self.filename, badfilename) except OSError as e: logger.error(self.tr("rename(%s,%s) failed: %s") % (self.filename, badfilename, e.strerror)) raise else: logger.debug(self.tr("renamed bad varspace %s to '%s'") % (self.filename, badfilename)) self.create_default_config() self.default_config = True logger.debug(self.tr("created default varspace '%s'") % self.filename) else: self.default_config = False logger.debug(self.tr("read existing varspace '%s'") % self.filename) # convenience - flatten nested config dict to access it via self.config.sectionname.varname self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever self.vars = DictDotLookup(self.var_dict)
class MyConfig(object): """ This class hosts all functions related to the Config File. """ def __init__(self): """ initialize the varspace of an existing plugin instance init_varspace() is a superclass method of plugin """ self.folder = os.path.join(g.folder, c.DEFAULT_CONFIG_DIR) self.filename = os.path.join(self.folder, 'config' + c.CONFIG_EXTENSION) self.version_mismatch = '' # no problem for now self.default_config = False # whether a new name was generated self.var_dict = dict() self.spec = ConfigObj(CONFIG_SPEC, interpolation=False, list_values=False, _inspec=True) # try: self.load_config() self.update_config() # The following settings won't be modified after a change in the configuration window. # If a setting need to be updated when the configuration changes, move it to the update_config() function self.mode3d = self.vars.General['mode3d'] self.machine_type = self.vars.General['machine_type'] self.fitting_tolerance = self.vars.Import_Parameters[ 'fitting_tolerance'] self.point_tolerance = self.vars.Import_Parameters['point_tolerance'] self.metric = 1 # true unit is determined while importing self.tool_units = self.vars.General[ 'tool_units'] # store the initial tool_units (we don't want it to change until software restart) self.tool_units_metric = 0 if self.vars.General[ 'tool_units'] == 'in' else 1 # except Exception, msg: # logger.warning(self.tr("Config loading failed: %s") % msg) # return False def tr(self, string_to_translate): """ Translate a string using the QCoreApplication translation framework @param string_to_translate: a unicode string @return: the translated unicode string if it was possible to translate """ return text_type( QtCore.QCoreApplication.translate('MyConfig', string_to_translate)) def update_config(self): """ Call this function each time the self.var_dict is updated (eg when the configuration window changes some settings) """ # convenience - flatten nested config dict to access it via self.config.sectionname.varname self.vars = DictDotLookup(self.var_dict) # add here any update needed for the internal variables of this class def make_settings_folder(self): """Create settings folder if necessary""" try: os.mkdir(self.folder) except OSError: pass def load_config(self): """Load Config File""" if os.path.isfile(self.filename): try: # file exists, read & validate it self.var_dict = ConfigObj(self.filename, configspec=CONFIG_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) if validate_errors: logger.error(self.tr("errors reading %s:") % self.filename) for entry in validate_errors: section_list, key, error = entry if key is not None: section_list.append(key) else: section_list.append('[missing section]') section_string = ', '.join(section_list) if not error: error = self.tr('Missing value or section.') logger.error(section_string + ' = ' + error) if validate_errors: raise BadConfigFileError("syntax errors in config file") # check config file version against internal version if CONFIG_VERSION: fileversion = self.var_dict['Version'][ 'config_version'] # this could raise KeyError if fileversion != CONFIG_VERSION: raise VersionMismatchError(fileversion, CONFIG_VERSION) except VersionMismatchError: #raise VersionMismatchError(fileversion, CONFIG_VERSION) # version mismatch flag, it will be used to display an error. self.version_mismatch = self.tr( "The configuration file version ({0}) doesn't match the software expected version ({1}).\n\nYou have to delete (or carefully edit) the configuration file \"{2}\" to solve the problem." ).format(fileversion, CONFIG_VERSION, self.filename) except Exception as inst: logger.error(inst) (base, ext) = os.path.splitext(self.filename) badfilename = base + c.BAD_CONFIG_EXTENSION logger.debug( self.tr("trying to rename bad cfg %s to %s") % (self.filename, badfilename)) try: os.rename(self.filename, badfilename) except OSError as e: logger.error( self.tr("rename(%s,%s) failed: %s") % (self.filename, badfilename, e.strerror)) raise else: logger.debug( self.tr("renamed bad varspace %s to '%s'") % (self.filename, badfilename)) self.create_default_config() self.default_config = True logger.debug( self.tr("created default varspace '%s'") % self.filename) else: self.default_config = False # logger.debug(self.dir()) # logger.debug(self.tr("created default varspace '%s'") % self.filename) # logger.debug(self.tr("read existing varspace '%s'") % self.filename) else: self.create_default_config() self.default_config = True logger.debug( self.tr("created default varspace '%s'") % self.filename) self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever def create_default_config(self): # check for existing setting folder or create one self.make_settings_folder() # derive config file with defaults from spec self.var_dict = ConfigObj(configspec=CONFIG_SPEC) _vdt = Validator() self.var_dict.validate(_vdt, copy=True) self.var_dict.filename = self.filename self.var_dict.write() def _save_varspace(self): """Saves Variables space""" self.var_dict.filename = self.filename self.var_dict.write() def print_vars(self): """Prints Variables""" print("Variables:") for k, v in self.var_dict['Variables'].items(): print(k, "=", v) def makeConfigWindgets(self): """ Build the configuration widgets and store them into a dictionary. The structure of the dictionnary must match the structure of the configuration file. The names of the keys must be identical to those used in the configfile. If a name is declared in the configfile but not here, it simply won't appear in the config window (the config_version for example must not be modified by the user, so it is not declared here) """ self.cfg_widget_def = \ { '__section_title__': { # This section is only used for assigning titles to the keys of the dictionnary (= name of the sections used in the config file). # This name is displayed in the tabs of the configuration window ; if no name is provided, the key name is used. A same title may be used for several keys : in this case, all the items that belongs to this section are regrouped into the same tab. # Note: the title may be specified in the section itselt too, using special entry "'__section_title__': Title to use" 'Tool_Parameters': self.tr("Tools table"), 'Custom_Actions' : self.tr("Custom actions"), }, 'Paths': { '__section_title__': self.tr("Software config"), 'import_dir': CfgLineEdit(self.tr('Default look for DXF files in:')), 'output_dir': CfgLineEdit(self.tr('Default export generated GCODE to:')), }, 'Filters': { '__section_title__': self.tr("Software config"), 'pstoedit_cmd': CfgLineEdit(self.tr('pstoedit command location:')), 'pstoedit_opt': CfgListEdit(self.tr('pstoedit options:'), ','), }, 'Axis_letters': { '__section_title__': self.tr("Machine config"), 'ax1_letter': CfgLineEdit(self.tr('Letter used for first axis:')), 'ax2_letter': CfgLineEdit(self.tr('Letter used for second axis:')), 'ax3_letter': CfgLineEdit(self.tr('Letter used for third axis:')), }, 'Plane_Coordinates': { '__section_title__': self.tr("Machine config"), 'axis1_start_end': CfgDoubleSpinBox(self.tr('Start/End coordinate for first axis:')), 'axis2_start_end': CfgDoubleSpinBox(self.tr('Start/End coordinate for second axis:')), }, 'Depth_Coordinates': { '__section_title__': self.tr("Machine config"), 'axis3_retract': CfgDoubleSpinBox(self.tr('Third axis default retraction coordinate:')), 'axis3_safe_margin': CfgDoubleSpinBox(self.tr('Third axis default safe coordinate:')), 'axis3_start_mill_depth': CfgDoubleSpinBox(self.tr('Third axis default workpiece origin:')), 'axis3_slice_depth': CfgDoubleSpinBox(self.tr('Third axis default slice depth:')), 'axis3_mill_depth': CfgDoubleSpinBox(self.tr('Third axis default final mill depth:')), }, 'Feed_Rates': { '__section_title__': self.tr("Machine config"), 'f_g1_plane': CfgDoubleSpinBox(self.tr('G1 feed rate for first and second axis (2D plane):'), ' mm/min'), 'f_g1_depth': CfgDoubleSpinBox(self.tr('G1 feed rate for third axis:'), ' mm/min'), }, 'General': { '__section_title__': self.tr("Software config"), 'mode3d': CfgCheckBox(self.tr('3D mode (requires OpenGL - Needs a software restart)')), 'write_to_stdout': CfgCheckBox(self.tr('Export GCODE to stdout (instead of a file)')), 'show_disabled_paths': CfgCheckBox(self.tr('Default enable "Show Disabled Paths"')), 'live_update_export_route': CfgCheckBox(self.tr('Default enable "Live Update Export Route"')), 'split_line_segments': CfgCheckBox(self.tr('Default enable "Split Line Segments" (create tabs on last slices)')), 'automatic_cutter_compensation': CfgCheckBox(self.tr('Default enable "Automatic Cutter Compensation"')), 'machine_type': CfgComboBox(self.tr('Default machine type at startup:')), 'tool_units': CfgComboBox(self.tr('Units for tools (needs a software restart):')), #'test': #{ # 'test_niveau_2': CfgCheckBox('Pour test'), # 'test2_niveau_2': CfgComboBox('Pour test', ('milling', 'lathe', 'drag_knife'), 'milling'), #}, }, 'Cutter_Compensation': { '__section_title__': self.tr("Output settings"), 'done_by_machine': CfgCheckBox(self.tr('Cutter compensation is done by machine (check this box if the machine reconizes G41 and G42 commands / uncheck it otherwise)')), }, 'Drag_Knife_Options': { 'drag_angle': CfgDoubleSpinBox(self.tr('Angle above which the tool retracts to slice depth (see "Third axis slice depth parameter"):'), u'°'), #u for unicode }, 'Route_Optimisation': { '__section_title__': self.tr("Output settings"), 'default_TSP': CfgCheckBox(self.tr('Default enable the TSP output path optimisation for each shape (TSP = Travelling Salesman Problem method)')), 'TSP_shape_order': CfgComboBox(self.tr('"Constrain order only" mixes fixed and optimized shapes\n"Constrain place after" always place optimized shapes after fixed shapes:')), 'mutation_rate': CfgDoubleSpinBox(self.tr('Mutation rate for TSP optimizer:')), 'max_population': CfgSpinBox(self.tr('Max population for the TSP optimizer:')), 'max_iterations': CfgSpinBox(self.tr('Max iterations for the TSP optimizer:')), 'begin_art': CfgComboBox(self.tr('TSP start method:')), }, 'Import_Parameters': { '__section_title__': self.tr("Output settings"), 'point_tolerance': CfgDoubleSpinBox(self.tr('DXF default import point tolerance:'), '', None, None, 5), 'spline_check': CfgSpinBox(self.tr('DXF import spline check:')), 'fitting_tolerance': CfgDoubleSpinBox(self.tr('DXF default import fit tolerance:'), '', None, None, 5), 'insert_at_block_layer': CfgCheckBox(self.tr('insert elements which are part of a block to layer where the block is inserted')), }, 'Layer_Options': { '__section_title__': self.tr("Automatic tool config"), 'id_float_separator': CfgLineEdit(self.tr('Separator between identifier and value:')), 'mill_depth_identifiers': CfgListEdit(self.tr('Identifiers that can be used for Final mill depth:'), ','), 'slice_depth_identifiers': CfgListEdit(self.tr('Identifiers that can be used for Infeed depth:'), ','), 'start_mill_depth_identifiers': CfgListEdit(self.tr('Identifiers that can be used for Workpiece top:'), ','), 'retract_identifiers': CfgListEdit(self.tr('Identifiers that can be used for Z Retraction area:'), ','), 'safe_margin_identifiers': CfgListEdit(self.tr('Identifiers that can be used for Z Safety margin:'), ','), 'f_g1_plane_identifiers': CfgListEdit(self.tr('Identifiers that can be used for G1 feed rate of XY plane:'), ','), 'f_g1_depth_identifiers': CfgListEdit(self.tr('Identifiers that can be used for G1 feed rate of Z:'), ','), 'tool_nr_identifiers': CfgListEdit(self.tr('Identifiers that can be used for tool number selection:'), ','), 'tool_diameter_identifiers': CfgListEdit(self.tr('Identifiers that can be used for tool diameter setting:'), ','), 'spindle_speed_identifiers': CfgListEdit(self.tr('Identifiers that can be used for spindle speed:'), ','), 'start_radius_identifiers': CfgListEdit(self.tr('Identifiers that can be used for start radius:'), ','), }, 'Tool_Parameters': CfgTableToolParameters(self.tr('Define the tools here:')), 'Custom_Actions': CfgTableCustomActions(self.tr('Define here custom GCODE that can be inserted anywhere in the program:')), 'Logging': { '__section_title__': self.tr("Software config"), 'logfile': CfgLineEdit(self.tr('File used for logging (software restart needed):')), 'console_loglevel': CfgComboBox(self.tr('Log any message with importance >= to log level on stderr console (software restart needed):')), 'file_loglevel': CfgComboBox(self.tr('Log any message with importance >= to log level in logfile (software restart needed):')), 'window_loglevel': CfgComboBox(self.tr('Log any message with importance >= to log level on the message window (software restart needed):')), }, } return self.cfg_widget_def
class MyConfig(object): """ This class hosts all functions related to the Config File. """ def __init__(self, script_dir): """ initialize the varspace of an existing plugin instance init_varspace() is a superclass method of plugin """ self.folder = script_dir + '\\config' self.file_name = os.path.join(self.folder, 'config' + c.CONFIG_EXTENSION) self.version_mismatch = '' # no problem for now self.default_config = False # whether a new name was generated self.var_dict = dict() self.spec = ConfigObj(CONFIG_SPEC, interpolation=False, list_values=False, _inspec=True) # try: self.load_config() self.update_config() # The following settings won't be modified after a change in the configuration window. # If a setting need to be updated when the configuration changes, move it to the update_config() function self.mode3d = self.vars.General['mode3d'] self.machine_type = self.vars.General['machine_type'] self.fitting_tolerance = self.vars.Import_Parameters[ 'fitting_tolerance'] self.point_tolerance = self.vars.Import_Parameters['point_tolerance'] self.metric = 1 # true unit is determined while importing self.tool_units = self.vars.General[ 'tool_units'] # store the initial tool_units (we don't want it to change until software restart) self.tool_units_metric = 0 if self.vars.General[ 'tool_units'] == 'in' else 1 def update_config(self): """ Call this function each time the self.var_dict is updated (eg when the configuration window changes some settings) """ # convenience - flatten nested config dict to access it via self.config.sectionname.varname self.vars = DictDotLookup(self.var_dict) # add here any update needed for the internal variables of this class def make_settings_folder(self): """Create settings folder if necessary""" try: os.makedirs(self.folder) except OSError: pass def load_config(self): """Load Config File""" print(self.file_name) if os.path.isfile(self.file_name): try: # file exists, read & validate it self.var_dict = ConfigObj(self.file_name, configspec=CONFIG_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) except self.var_dict == None: #rw logger.error( "reading values from postprocessorconfig file error") #rw self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever
def load_config(self): """Load Config File""" if os.path.isfile(self.filename): try: # file exists, read & validate it self.var_dict = ConfigObj(self.filename, configspec=CONFIG_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) if validate_errors: logger.error(self.tr("errors reading %s:") % self.filename) for entry in validate_errors: section_list, key, error = entry if key is not None: section_list.append(key) else: section_list.append('[missing section]') section_string = ', '.join(section_list) if not error: error = self.tr('Missing value or section.') logger.error(section_string + ' = ' + error) if validate_errors: raise BadConfigFileError("syntax errors in config file") # check config file version against internal version if CONFIG_VERSION: fileversion = self.var_dict['Version']['config_version'] # this could raise KeyError if fileversion != CONFIG_VERSION: raise VersionMismatchError(fileversion, CONFIG_VERSION) except VersionMismatchError: raise VersionMismatchError(fileversion, CONFIG_VERSION) # TODO pop-up error? except Exception as inst: logger.error(inst) (base, ext) = os.path.splitext(self.filename) badfilename = base + c.BAD_CONFIG_EXTENSION logger.debug(self.tr("trying to rename bad cfg %s to %s") % (self.filename, badfilename)) try: os.rename(self.filename, badfilename) except OSError as e: logger.error(self.tr("rename(%s,%s) failed: %s") % (self.filename, badfilename, e.strerror)) raise else: logger.debug(self.tr("renamed bad varspace %s to '%s'") % (self.filename, badfilename)) self.create_default_config() self.default_config = True logger.debug(self.tr("created default varspace '%s'") % self.filename) else: self.default_config = False # logger.debug(self.dir()) # logger.debug(self.tr("created default varspace '%s'") % self.filename) # logger.debug(self.tr("read existing varspace '%s'") % self.filename) else: self.create_default_config() self.default_config = True logger.debug(self.tr("created default varspace '%s'") % self.filename) self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever
class MyConfig(object): """ This class hosts all functions related to the Config File. """ def __init__(self): """ initialize the varspace of an existing plugin instance init_varspace() is a superclass method of plugin """ self.folder = os.path.join(g.folder, c.DEFAULT_CONFIG_DIR) self.filename = os.path.join(self.folder, 'config' + c.CONFIG_EXTENSION) self.default_config = False # whether a new name was generated self.var_dict = dict() self.spec = ConfigObj(CONFIG_SPEC, interpolation=False, list_values=False, _inspec=True) # try: self.load_config() # convenience - flatten nested config dict to access it via self.config.sectionname.varname self.vars = DictDotLookup(self.var_dict) self.mode3d = self.vars.General['mode3d'] self.machine_type = self.vars.General['machine_type'] self.fitting_tolerance = self.vars.Import_Parameters['fitting_tolerance'] self.point_tolerance = self.vars.Import_Parameters['point_tolerance'] self.metric = 1 # true unit is determined while importing self.tool_units_metric = 0 if self.vars.General['tool_units'] == 'in' else 1 # except Exception, msg: # logger.warning(self.tr("Config loading failed: %s") % msg) # return False def tr(self, string_to_translate): """ Translate a string using the QCoreApplication translation framework @param string_to_translate: a unicode string @return: the translated unicode string if it was possible to translate """ return text_type(QtCore.QCoreApplication.translate('MyConfig', string_to_translate)) def make_settings_folder(self): """Create settings folder if necessary""" try: os.mkdir(self.folder) except OSError: pass def load_config(self): """Load Config File""" if os.path.isfile(self.filename): try: # file exists, read & validate it self.var_dict = ConfigObj(self.filename, configspec=CONFIG_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) if validate_errors: logger.error(self.tr("errors reading %s:") % self.filename) for entry in validate_errors: section_list, key, error = entry if key is not None: section_list.append(key) else: section_list.append('[missing section]') section_string = ', '.join(section_list) if not error: error = self.tr('Missing value or section.') logger.error(section_string + ' = ' + error) if validate_errors: raise BadConfigFileError("syntax errors in config file") # check config file version against internal version if CONFIG_VERSION: fileversion = self.var_dict['Version']['config_version'] # this could raise KeyError if fileversion != CONFIG_VERSION: raise VersionMismatchError(fileversion, CONFIG_VERSION) except VersionMismatchError: raise VersionMismatchError(fileversion, CONFIG_VERSION) # TODO pop-up error? except Exception as inst: logger.error(inst) (base, ext) = os.path.splitext(self.filename) badfilename = base + c.BAD_CONFIG_EXTENSION logger.debug(self.tr("trying to rename bad cfg %s to %s") % (self.filename, badfilename)) try: os.rename(self.filename, badfilename) except OSError as e: logger.error(self.tr("rename(%s,%s) failed: %s") % (self.filename, badfilename, e.strerror)) raise else: logger.debug(self.tr("renamed bad varspace %s to '%s'") % (self.filename, badfilename)) self.create_default_config() self.default_config = True logger.debug(self.tr("created default varspace '%s'") % self.filename) else: self.default_config = False # logger.debug(self.dir()) # logger.debug(self.tr("created default varspace '%s'") % self.filename) # logger.debug(self.tr("read existing varspace '%s'") % self.filename) else: self.create_default_config() self.default_config = True logger.debug(self.tr("created default varspace '%s'") % self.filename) self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever def create_default_config(self): # check for existing setting folder or create one self.make_settings_folder() # derive config file with defaults from spec self.var_dict = ConfigObj(configspec=CONFIG_SPEC) _vdt = Validator() self.var_dict.validate(_vdt, copy=True) self.var_dict.filename = self.filename self.var_dict.write() def _save_varspace(self): """Saves Variables space""" self.var_dict.filename = self.filename self.var_dict.write() def print_vars(self): """Prints Variables""" print("Variables:") for k, v in self.var_dict['Variables'].items(): print(k, "=", v)
class MyPostProConfig(object): """ This class hosts all functions related to the PostProConfig File. """ def __init__(self, filename='postpro_config' + c.CONFIG_EXTENSION): """ initialize the varspace of an existing plugin instance init_varspace() is a superclass method of plugin @param filename: The filename for the creation of a new config file and the filename of the file to read config from. """ self.folder = os.path.join(g.folder, c.DEFAULT_POSTPRO_DIR) self.filename = os.path.join(self.folder, filename) self.default_config = False # whether a new name was generated self.var_dict = dict() self.spec = ConfigObj(POSTPRO_SPEC, interpolation=False, list_values=False, _inspec=True) def tr(self, string_to_translate): """ Translate a string using the QCoreApplication translation framework @param: string_to_translate: a unicode string @return: the translated unicode string if it was possible to translate """ return text_type(QtCore.QCoreApplication.translate("MyPostProConfig", string_to_translate)) def load_config(self): """ This method tries to load the defined postprocessor file given in self.filename. If this fails it will create a new one """ try: # file exists, read & validate it self.var_dict = ConfigObj(self.filename, configspec=POSTPRO_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) if validate_errors: g.logger.logger.error(self.tr("errors reading %s:") % self.filename) for entry in validate_errors: section_list, key, error = entry if key is not None: section_list.append(key) else: section_list.append('[missing section]') section_string = ', '.join(section_list) if error == False: error = self.tr('Missing value or section.') g.logger.logger.error( section_string + ' = ' + error) if validate_errors: raise BadConfigFileError(self.tr("syntax errors in postpro_config file")) # check config file version against internal version if POSTPRO_VERSION: fileversion = self.var_dict['Version']['config_version'] # this could raise KeyError if fileversion != POSTPRO_VERSION: raise VersionMismatchError(fileversion, POSTPRO_VERSION) except VersionMismatchError: raise VersionMismatchError(fileversion, POSTPRO_VERSION) except Exception as inst: logger.error(inst) (base, ext) = os.path.splitext(self.filename) badfilename = base + c.BAD_CONFIG_EXTENSION logger.debug(self.tr("trying to rename bad cfg %s to %s") % (self.filename, badfilename)) try: os.rename(self.filename, badfilename) except OSError as e: logger.error(self.tr("rename(%s,%s) failed: %s") % (self.filename, badfilename, e.strerror)) raise else: logger.debug(self.tr("renamed bad varspace %s to '%s'") % (self.filename, badfilename)) self.create_default_config() self.default_config = True logger.debug(self.tr("created default varspace '%s'") % self.filename) else: self.default_config = False logger.debug(self.tr("read existing varspace '%s'") % self.filename) # convenience - flatten nested config dict to access it via self.config.sectionname.varname self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever self.vars = DictDotLookup(self.var_dict) def make_settings_folder(self): """ This method creates the postprocessor settings folder if necessary """ try: os.mkdir(self.folder) except OSError: pass def create_default_config(self): """ If no postprocessor config file exists this function is called to generate the config file based on its specification. """ # check for existing setting folder or create one self.make_settings_folder() # derive config file with defaults from spec logger.debug(POSTPRO_SPEC) self.var_dict = ConfigObj(configspec=POSTPRO_SPEC) _vdt = Validator() self.var_dict.validate(_vdt, copy=True) self.var_dict.filename = self.filename self.var_dict.write() # def _save_varspace(self): # self.var_dict.filename = self.filename # self.var_dict.write() # def print_vars(self): """ Print all the variables with their values """ print("Variables:") for k, v in self.var_dict['Variables'].items(): print(k, "=", v)
class MyPostProConfig(object): """ This class hosts all functions related to the PostProConfig File. """ def __init__(self, filename='postpro_config' + c.CONFIG_EXTENSION): """ initialize the varspace of an existing plugin instance init_varspace() is a superclass method of plugin @param filename: The filename for the creation of a new config file and the filename of the file to read config from. """ self.folder = os.path.join(g.folder, c.DEFAULT_POSTPRO_DIR) self.filename = os.path.join(self.folder, filename) self.version_mismatch = '' # no problem for now self.default_config = False # whether a new name was generated self.var_dict = dict() self.spec = ConfigObj(POSTPRO_SPEC, interpolation=False, list_values=False, _inspec=True) def load_config(self): """ This method tries to load the defined postprocessor file given in self.filename. If this fails it will create a new one """ try: # file exists, read & validate it self.var_dict = ConfigObj(self.filename, configspec=POSTPRO_SPEC) _vdt = Validator() result = self.var_dict.validate(_vdt, preserve_errors=True) validate_errors = flatten_errors(self.var_dict, result) if validate_errors: logger.error(self.tr("errors reading %s:") % self.filename) for entry in validate_errors: section_list, key, error = entry if key is not None: section_list.append(key) else: section_list.append('[missing section]') section_string = ', '.join(section_list) if error == False: error = self.tr('Missing value or section.') logger.error(section_string + ' = ' + error) if validate_errors: raise BadConfigFileError( self.tr("syntax errors in postpro_config file")) # check config file version against internal version if POSTPRO_VERSION: fileversion = self.var_dict['Version'][ 'config_version'] # this could raise KeyError if fileversion != POSTPRO_VERSION: raise VersionMismatchError(fileversion, POSTPRO_VERSION) except VersionMismatchError: # version mismatch flag, it will be used to display an error. self.version_mismatch = self.tr( "The postprocessor configuration file version ({0}) doesn't match the software expected version ({1}).\n\nYou have to delete (or carefully edit) the configuration file \"{2}\" to solve the problem." ).format(fileversion, POSTPRO_VERSION, self.filename) except Exception as inst: #logger.error(inst) (base, ext) = os.path.splitext(self.filename) badfilename = base + c.BAD_CONFIG_EXTENSION logger.debug( self.tr("trying to rename bad cfg %s to %s") % (self.filename, badfilename)) try: os.rename(self.filename, badfilename) except OSError as e: logger.error( self.tr("rename(%s,%s) failed: %s") % (self.filename, badfilename, e.strerror)) raise else: logger.debug( self.tr("renamed bad varspace %s to '%s'") % (self.filename, badfilename)) self.create_default_config() self.default_config = True logger.debug( self.tr("created default varspace '%s'") % self.filename) else: self.default_config = False logger.debug( self.tr("read existing varspace '%s'") % self.filename) # convenience - flatten nested config dict to access it via self.config.sectionname.varname self.var_dict.main.interpolation = False # avoid ConfigObj getting too clever self.update_config() def update_config(self): """ Call this function each time the self.var_dict is updated (eg when the postprocessor configuration window changes some settings) """ # convenience - flatten nested config dict to access it via self.config.sectionname.varname self.vars = DictDotLookup(self.var_dict) # add here any update needed for the internal variables of this class def make_settings_folder(self): """ This method creates the postprocessor settings folder if necessary """ try: os.mkdir(self.folder) except OSError: pass def create_default_config(self): """ If no postprocessor config file exists this function is called to generate the config file based on its specification. """ # check for existing setting folder or create one self.make_settings_folder() # derive config file with defaults from spec logger.debug(POSTPRO_SPEC) self.var_dict = ConfigObj(configspec=POSTPRO_SPEC) _vdt = Validator() self.var_dict.validate(_vdt, copy=True) self.var_dict.filename = self.filename self.var_dict.write() def save_varspace(self): self.var_dict.filename = self.filename self.var_dict.write() def print_vars(self): """ Print all the variables with their values """ print("Variables:") for k, v in self.var_dict['Variables'].items(): print(k, "=", v) @staticmethod def tr(string_to_translate): """ Translate a string using the QCoreApplication translation framework @param string_to_translate: a unicode string @return: the translated unicode string if it was possible to translate """ return text_type( QtCore.QCoreApplication.translate('MyPostProConfig', string_to_translate)) @staticmethod def makeConfigWidgets(): """ Build the postprocessor configuration widgets and store them into a dictionary. The structure of the dictionnary must match the structure of the postprocessor configuration file. The names of the keys must be identical to those used in the configfile. If a name is declared in the configfile but not here, it simply won't appear in the config window (the config_version for example must not be modified by the user, so it is not declared here) """ cfg_widget_def = OrderedDict([ ('General', OrderedDict([ ('__section_title__', MyPostProConfig.tr("Software config")), ('__subtitle__', CfgSubtitle(MyPostProConfig.tr("Output specifications"))), ('output_text', CfgLineEdit( MyPostProConfig.tr('Output format description:'))), ('output_format', CfgLineEdit(MyPostProConfig.tr('Output file extension:'))), ('output_type', CfgComboBox(MyPostProConfig.tr('Output type:'))), ('__subtitle2__', CfgSubtitle(MyPostProConfig.tr("Output options"))), ('abs_export', CfgCheckBox( MyPostProConfig.tr('Export absolute coordinates'))), ('cancel_cc_for_depth', CfgCheckBox( MyPostProConfig.tr( 'Cancel cutter compensation at each slice'))), ('cc_outside_the_piece', CfgCheckBox( MyPostProConfig.tr( 'Perform cutter compensation outside the piece'))), ('export_ccw_arcs_only', CfgCheckBox( MyPostProConfig.tr('Export only counter clockwise arcs')) ), ('max_arc_radius', CfgDoubleSpinBox(MyPostProConfig.tr('Maximum arc radius:'))), ('__subtitle3__', CfgSubtitle(MyPostProConfig.tr("G-code constants"))), ('code_begin_units_mm', CfgLineEdit(MyPostProConfig.tr('Units in millimeters:'))), ('code_begin_units_in', CfgLineEdit(MyPostProConfig.tr('Units in inch:'))), ('code_begin_prog_abs', CfgLineEdit(MyPostProConfig.tr('Absolute programming:'))), ('code_begin_prog_inc', CfgLineEdit(MyPostProConfig.tr('Incremental programming:'))), ('code_begin', CfgTextEdit(MyPostProConfig.tr('Startup:'))), ('code_end', CfgTextEdit(MyPostProConfig.tr('End:'))) ])), ('Number_Format', OrderedDict([ ('__section_title__', MyPostProConfig.tr("Output formatting")), ('__subtitle__', CfgSubtitle(MyPostProConfig.tr("Output formatting"))), ('signed_values', CfgCheckBox( MyPostProConfig. tr("Prepend numbers with the '+' sign for positive values" ))), ('pre_decimals', CfgSpinBox( MyPostProConfig.tr( 'Number of digits before the decimal separator:'))), ('pre_decimal_zero_padding', CfgCheckBox( MyPostProConfig.tr( "Padding with '0' digit before the decimal separator" ))), ('post_decimals', CfgSpinBox( MyPostProConfig.tr( 'Number of digits after the decimal separator:'))), ('post_decimal_zero_padding', CfgCheckBox( MyPostProConfig. tr("Padding with '0' digit after the decimal separator")) ), ('decimal_separator', CfgLineEdit(MyPostProConfig.tr('Decimal separator:'))) ])), ('Line_Numbers', OrderedDict([ ('__section_title__', MyPostProConfig.tr("Output formatting")), ('__subtitle__', CfgSubtitle(MyPostProConfig.tr("Line numbers"))), ('use_line_nrs', CfgCheckBox(MyPostProConfig.tr('Export line numbers'))), ('line_nrs_begin', CfgSpinBox(MyPostProConfig.tr('Line number starts at:'))), ('line_nrs_step', CfgSpinBox(MyPostProConfig.tr('Line number step:'))) ])), ('Program', OrderedDict([ ('__section_title__', MyPostProConfig.tr("G-code codes")), ('tool_change', CfgLineEdit(MyPostProConfig.tr('Tool change:'))), ('feed_change', CfgLineEdit(MyPostProConfig.tr('Feed rate change:'))), ('rap_pos_plane', CfgLineEdit( MyPostProConfig.tr('Rapid positioning for XY plane:'))), ('rap_pos_depth', CfgLineEdit( MyPostProConfig.tr('Rapid positioning for Z plane:'))), ('lin_mov_plane', CfgLineEdit( MyPostProConfig.tr('Linear feed move for XY plane:'))), ('lin_mov_depth', CfgLineEdit( MyPostProConfig.tr('Linear feed move for Z plane:'))), ('arc_int_cw', CfgLineEdit(MyPostProConfig.tr('Clockwise feed move:'))), ('arc_int_ccw', CfgLineEdit( MyPostProConfig.tr('Counter clockwise feed move:'))), ('cutter_comp_off', CfgLineEdit( MyPostProConfig.tr('Disable cutter compensation:'))), ('cutter_comp_left', CfgLineEdit( MyPostProConfig.tr('Left cutter compensation:'))), ('cutter_comp_right', CfgLineEdit( MyPostProConfig.tr('Right cutter compensation:'))), ('pre_shape_cut', CfgLineEdit( MyPostProConfig.tr('Placed in front of any shape:'))), ('post_shape_cut', CfgLineEdit(MyPostProConfig.tr('Placed after any shape:'))), ('comment', CfgLineEdit( MyPostProConfig.tr('Comment for current shape:'))) ])) ]) return cfg_widget_def