flatcam/defaults.py

992 lines
37 KiB
Python

import os
import stat
import sys
from copy import deepcopy
from appCommon.Common import LoudDict
from camlib import to_dict, CNCjob, Geometry
import simplejson
import logging
import gettext
import appTranslation as fcTranslate
import builtins
from appParsers.ParseExcellon import Excellon
from appParsers.ParseGerber import Gerber
fcTranslate.apply_language('strings')
if '_' not in builtins.__dict__:
_ = gettext.gettext
# log = logging.getLogger('FlatCAMDefaults')
log = logging.getLogger('base')
class FlatCAMDefaults:
factory_defaults = {
# Global
"version": 8.992, # defaults format version, not necessarily equal to app version
"first_run": True,
"root_folder_path": '',
"global_serial": 0,
"global_stats": dict(),
"global_tabs_detachable": True,
"global_coordsbar_show": True,
"global_delta_coordsbar_show": False,
"global_statusbar_show": True,
"global_jump_ref": 'abs',
"global_locate_pt": 'bl',
"global_toolbar_view": 511,
"global_background_timeout": 300000, # Default value is 5 minutes
"global_verbose_error_level": 0, # Shell verbosity 0 = default
# (python trace only for unknown errors),
# 1 = show trace(show trace always),
# 2 = (For the future).
"global_grid_context_menu": {
'in': [0.01, 0.02, 0.025, 0.05, 0.1],
'mm': [0.1, 0.2, 0.5, 1, 2.54]
},
# Persistence
"global_last_folder": None,
"global_last_save_folder": None,
# Default window geometry
"global_def_win_x": 100,
"global_def_win_y": 100,
"global_def_win_w": 1024,
"global_def_win_h": 650,
"global_def_notebook_width": 1,
# Constants...
"global_defaults_save_period_ms": 20000, # Time between default saves.
"global_shell_shape": [500, 300], # Shape of the shell in pixels.
"global_recent_limit": 10, # Max. items in recent list.
"fit_key": 'V',
"zoom_out_key": '-',
"zoom_in_key": '=',
"grid_toggle_key": 'G',
"global_zoom_ratio": 1.5,
"global_point_clipboard_format": "(%.*f, %.*f)",
"global_zdownrate": None,
"global_tcl_path": '',
# General APP Preferences
"units": "MM",
"decimals_inch": 4,
"decimals_metric": 4,
"global_graphic_engine": '3D',
"global_app_level": 'b',
"global_portable": False,
"global_language": 'English',
"global_systray_icon": True,
"global_shell_at_startup": False, # Show the shell at startup.
"global_project_at_startup": False,
"global_version_check": True,
"global_send_stats": True,
"global_worker_number": int((os.cpu_count()) / 2) if os.cpu_count() > 4 else 2,
"global_tolerance": 0.005,
"global_save_compressed": True,
"global_compression_level": 3,
"global_autosave": False,
"global_autosave_timeout": 300000,
"global_tpdf_tmargin": 15.0,
"global_tpdf_bmargin": 10.0,
"global_tpdf_lmargin": 20.0,
"global_tpdf_rmargin": 20.0,
# General GUI Preferences
"global_theme": 'white',
"global_gray_icons": False,
"global_layout": "compact",
"global_hover": False,
"global_selection_shape": True,
"global_sel_fill": '#a5a5ffbf',
"global_sel_line": '#0000ffbf',
"global_alt_sel_fill": '#BBF268BF',
"global_alt_sel_line": '#006E20BF',
"global_draw_color": '#FF0000',
"global_sel_draw_color": '#0000FF',
"global_proj_item_color": '#000000',
"global_proj_item_dis_color": '#b7b7cb',
"global_project_autohide": True,
# General App Settings
"global_gridbar_show": True,
"global_gridx": 1.0,
"global_gridy": 1.0,
"global_snap_max": 0.05,
"global_workspace": False,
"global_workspaceT": "A4",
"global_workspace_orientation": 'p',
"global_axis": True,
"global_hud": True,
"global_grid_lines": True,
"global_grid_snap": True,
"global_cursor_type": "small",
"global_cursor_size": 20,
"global_cursor_width": 2,
"global_cursor_color": '#FF0000',
"global_cursor_color_enabled": True,
"global_pan_button": '2',
"global_mselect_key": 'Control',
"global_delete_confirmation": True,
"global_allow_edit_in_project_tab": False,
"global_open_style": True,
"global_toggle_tooltips": True,
"global_machinist_setting": False,
"global_bookmarks": dict(),
"global_bookmarks_limit": 10,
"global_activity_icon": 'Ball green',
# Gerber General
"gerber_plot": True,
"gerber_solid": True,
"gerber_multicolored": False,
"gerber_color_list": [],
"gerber_store_color_list": True,
"gerber_circle_steps": 64,
"gerber_use_buffer_for_union": True,
"gerber_clean_apertures": True,
"gerber_extra_buffering": True,
"gerber_plot_fill": '#BBF268BF',
"gerber_plot_line": '#006E20BF',
"gerber_def_units": 'IN',
"gerber_def_zeros": 'L',
"gerber_save_filters": "Gerber File .gbr (*.gbr);;Gerber File .bot (*.bot);;Gerber File .bsm (*.bsm);;"
"Gerber File .cmp (*.cmp);;Gerber File .crc (*.crc);;Gerber File .crs (*.crs);;"
"Gerber File .gb0 (*.gb0);;Gerber File .gb1 (*.gb1);;Gerber File .gb2 (*.gb2);;"
"Gerber File .gb3 (*.gb3);;Gerber File .gb4 (*.gb4);;Gerber File .gb5 (*.gb5);;"
"Gerber File .gb6 (*.gb6);;Gerber File .gb7 (*.gb7);;Gerber File .gb8 (*.gb8);;"
"Gerber File .gb9 (*.gb9);;Gerber File .gbd (*.gbd);;Gerber File .gbl (*.gbl);;"
"Gerber File .gbo (*.gbo);;Gerber File .gbp (*.gbp);;Gerber File .gbs (*.gbs);;"
"Gerber File .gdo (*.gdo);;Gerber File .ger (*.ger);;Gerber File .gko (*.gko);;"
"Gerber File .gm1 (*.gm1);;Gerber File .gm2 (*.gm2);;Gerber File .gm3 (*.gm3);;"
"Gerber File .grb (*.grb);;Gerber File .gtl (*.gtl);;Gerber File .gto (*.gto);;"
"Gerber File .gtp (*.gtp);;Gerber File .gts (*.gts);;Gerber File .ly15 (*.ly15);;"
"Gerber File .ly2 (*.ly2);;Gerber File .mil (*.mil);;"
"Gerber File .outline (*.outline);;Gerber File .pho (*.pho);;"
"Gerber File .plc (*.plc);;Gerber File .pls (*.pls);;Gerber File .smb (*.smb);;"
"Gerber File .smt (*.smt);;Gerber File .sol (*.sol);;Gerber File .spb (*.spb);;"
"Gerber File .spt (*.spt);;Gerber File .ssb (*.ssb);;Gerber File .sst (*.sst);;"
"Gerber File .stc (*.stc);;Gerber File .sts (*.sts);;Gerber File .top (*.top);;"
"Gerber File .tsm (*.tsm);;Gerber File .art (*.art)"
"All Files (*.*)",
# Gerber Options
"gerber_noncoppermargin": 0.1,
"gerber_noncopperrounded": False,
"gerber_bboxmargin": 0.1,
"gerber_bboxrounded": False,
# Gerber Advanced Options
"gerber_aperture_display": False,
"gerber_aperture_scale_factor": 1.0,
"gerber_aperture_buffer_factor": 0.0,
"gerber_follow": False,
"gerber_buffering": "full",
"gerber_delayed_buffering": True,
"gerber_simplification": False,
"gerber_simp_tolerance": 0.0005,
# Gerber Export
"gerber_exp_units": 'IN',
"gerber_exp_integer": 2,
"gerber_exp_decimals": 4,
"gerber_exp_zeros": 'L',
# Gerber Editor
"gerber_editor_sel_limit": 30,
"gerber_editor_newcode": 10,
"gerber_editor_newsize": 0.8,
"gerber_editor_newtype": 'C',
"gerber_editor_newdim": "0.5, 0.5",
"gerber_editor_array_size": 5,
"gerber_editor_lin_axis": 'X',
"gerber_editor_lin_pitch": 0.1,
"gerber_editor_lin_angle": 0.0,
"gerber_editor_circ_dir": 'CW',
"gerber_editor_circ_angle": 0.0,
"gerber_editor_scale_f": 1.0,
"gerber_editor_buff_f": 0.1,
"gerber_editor_ma_low": 0.0,
"gerber_editor_ma_high": 1.0,
# Excellon General
"excellon_plot": True,
"excellon_solid": True,
"excellon_multicolored": False,
"excellon_merge_fuse_tools": True,
"excellon_format_upper_in": 2,
"excellon_format_lower_in": 4,
"excellon_format_upper_mm": 3,
"excellon_format_lower_mm": 3,
"excellon_zeros": "T",
"excellon_units": "INCH",
"excellon_update": True,
"excellon_optimization_type": 'B',
"excellon_search_time": 3,
"excellon_save_filters": "Excellon File .txt (*.txt);;Excellon File .drd (*.drd);;"
"Excellon File .drill (*.drill);;"
"Excellon File .drl (*.drl);;Excellon File .exc (*.exc);;"
"Excellon File .ncd (*.ncd);;Excellon File .tap (*.tap);;"
"Excellon File .xln (*.xln);;All Files (*.*)",
"excellon_plot_fill": '#C40000BF',
"excellon_plot_line": '#750000BF',
# Excellon Options
"excellon_operation": "drill",
"excellon_milling_type": "drills",
"excellon_milling_dia": 0.8,
"excellon_tooldia": 0.8,
"excellon_slot_tooldia": 1.8,
# Excellon Advanced options
"excellon_tools_table_display": True,
"excellon_autoload_db": False,
# Excellon Export
"excellon_exp_units": 'INCH',
"excellon_exp_format": 'dec',
"excellon_exp_integer": 2,
"excellon_exp_decimals": 4,
"excellon_exp_zeros": 'LZ',
"excellon_exp_slot_type": 'routing',
# Excellon Editor
"excellon_editor_sel_limit": 30,
"excellon_editor_newdia": 1.0,
"excellon_editor_array_size": 5,
"excellon_editor_lin_dir": 'X',
"excellon_editor_lin_pitch": 2.54,
"excellon_editor_lin_angle": 0.0,
"excellon_editor_circ_dir": 'CW',
"excellon_editor_circ_angle": 12,
# Excellon Slots
"excellon_editor_slot_direction": 'X',
"excellon_editor_slot_angle": 0.0,
"excellon_editor_slot_length": 5.0,
# Excellon Slot Array
"excellon_editor_slot_array_size": 5,
"excellon_editor_slot_lin_dir": 'X',
"excellon_editor_slot_lin_pitch": 2.54,
"excellon_editor_slot_lin_angle": 0.0,
"excellon_editor_slot_circ_dir": 'CW',
"excellon_editor_slot_circ_angle": 0.0,
# Geometry General
"geometry_plot": True,
"geometry_multicolored": False,
"geometry_circle_steps": 64,
"geometry_cnctooldia": "2.4",
"geometry_merge_fuse_tools": True,
"geometry_plot_line": "#FF0000",
"geometry_optimization_type": 'R',
"geometry_search_time": 3,
# Geometry Options
"geometry_cutz": -2.4,
"geometry_vtipdia": 0.1,
"geometry_vtipangle": 30,
"geometry_multidepth": False,
"geometry_depthperpass": 0.8,
"geometry_travelz": 2,
"geometry_toolchange": False,
"geometry_toolchangez": 15.0,
"geometry_endz": 15.0,
"geometry_endxy": None,
"geometry_feedrate": 120,
"geometry_feedrate_z": 60,
"geometry_spindlespeed": 0,
"geometry_dwell": False,
"geometry_dwelltime": 1,
"geometry_ppname_g": 'default',
# Geometry Advanced Options
"geometry_toolchangexy": "0.0, 0.0",
"geometry_startz": None,
"geometry_feedrate_rapid": 1500,
"geometry_extracut": False,
"geometry_extracut_length": 0.1,
"geometry_z_pdepth": -0.02,
"geometry_f_plunge": False,
"geometry_spindledir": 'CW',
"geometry_feedrate_probe": 75,
"geometry_segx": 0.0,
"geometry_segy": 0.0,
"geometry_area_exclusion": False,
"geometry_area_shape": "polygon",
"geometry_area_strategy": "over",
"geometry_area_overz": 1.0,
"geometry_polish": False,
"geometry_polish_dia": 10.0,
"geometry_polish_pressure": -1.0,
"geometry_polish_travelz": 2.0,
"geometry_polish_margin": 0.0,
"geometry_polish_overlap": 5,
"geometry_polish_method": 0,
# Geometry Editor
"geometry_editor_sel_limit": 30,
"geometry_editor_milling_type": "cl",
# CNC Job General
"cncjob_plot": True,
"cncjob_tooldia": 1.0,
"cncjob_coords_type": "G90",
"cncjob_coords_decimals": 4,
"cncjob_fr_decimals": 2,
"cncjob_steps_per_circle": 64,
"cncjob_footer": False,
"cncjob_line_ending": False,
"cncjob_save_filters": "G-Code Files .nc (*.nc);;G-Code Files .din (*.din);;G-Code Files .dnc (*.dnc);;"
"G-Code Files .ecs (*.ecs);;G-Code Files .eia (*.eia);;G-Code Files .fan (*.fan);;"
"G-Code Files .fgc (*.fgc);;G-Code Files .fnc (*.fnc);;G-Code Files . gc (*.gc);;"
"G-Code Files .gcd (*.gcd);;G-Code Files .gcode (*.gcode);;G-Code Files .h (*.h);;"
"G-Code Files .hnc (*.hnc);;G-Code Files .i (*.i);;G-Code Files .min (*.min);;"
"G-Code Files .mpf (*.mpf);;G-Code Files .mpr (*.mpr);;G-Code Files .cnc (*.cnc);;"
"G-Code Files .ncc (*.ncc);;G-Code Files .ncg (*.ncg);;G-Code Files .ncp (*.ncp);;"
"G-Code Files .ngc (*.ngc);;G-Code Files .out (*.out);;G-Code Files .ply (*.ply);;"
"G-Code Files .sbp (*.sbp);;G-Code Files .tap (*.tap);;G-Code Files .xpi (*.xpi);;"
"All Files (*.*)",
"cncjob_plot_line": '#4650BDFF',
"cncjob_plot_fill": '#5E6CFFFF',
"cncjob_travel_line": '#B5AB3A4C',
"cncjob_travel_fill": '#F0E24D4C',
# CNC Job Options
"cncjob_plot_kind": 'all',
"cncjob_annotation": True,
# CNC Job Advanced Options
"cncjob_annotation_fontsize": 9,
"cncjob_annotation_fontcolor": '#990000',
# Autolevelling
"cncjob_al_status": False,
"cncjob_al_mode": 'grid',
"cncjob_al_method": 'v',
"cncjob_al_rows": 4,
"cncjob_al_columns": 4,
"cncjob_al_travelz": 2.0,
"cncjob_al_probe_depth": -1.0,
"cncjob_al_probe_fr": 120,
"cncjob_al_controller": 'MACH3',
"cncjob_al_grbl_jog_step": 5,
"cncjob_al_grbl_jog_fr": 1500,
"cncjob_al_grbl_travelz": 15.0,
# CNC Job (GCode) Editor
"cncjob_prepend": "",
"cncjob_append": "",
# Isolation Routing Tool
"tools_iso_tooldia": "0.1",
"tools_iso_order": 'rev',
"tools_iso_tool_type": 'C1',
"tools_iso_tool_vtipdia": 0.1,
"tools_iso_tool_vtipangle": 30,
"tools_iso_tool_cutz": -0.05,
"tools_iso_newdia": 0.1,
"tools_iso_passes": 1,
"tools_iso_overlap": 10,
"tools_iso_milling_type": "cl",
"tools_iso_follow": False,
"tools_iso_isotype": "full",
"tools_iso_rest": False,
"tools_iso_combine_passes": True,
"tools_iso_check_valid": False,
"tools_iso_isoexcept": False,
"tools_iso_selection": 0,
"tools_iso_poly_ints": False,
"tools_iso_force": True,
"tools_iso_area_shape": "square",
"tools_iso_plotting": 'normal',
# Drilling Tool
"tools_drill_tool_order": 'no',
"tools_drill_cutz": -1.7,
"tools_drill_multidepth": False,
"tools_drill_depthperpass": 0.7,
"tools_drill_travelz": 2,
"tools_drill_endz": 0.5,
"tools_drill_endxy": None,
"tools_drill_feedrate_z": 300,
"tools_drill_spindlespeed": 0,
"tools_drill_dwell": False,
"tools_drill_dwelltime": 1,
"tools_drill_toolchange": False,
"tools_drill_toolchangez": 15,
"tools_drill_ppname_e": 'default',
"tools_drill_drill_slots": False,
"tools_drill_drill_overlap": 0.0,
"tools_drill_last_drill": True,
# Advanced Options
"tools_drill_offset": 0.0,
"tools_drill_toolchangexy": "0.0, 0.0",
"tools_drill_startz": None,
"tools_drill_feedrate_rapid": 1500,
"tools_drill_z_pdepth": -0.02,
"tools_drill_feedrate_probe": 75,
"tools_drill_spindledir": 'CW',
"tools_drill_f_plunge": False,
"tools_drill_f_retract": False,
"tools_drill_area_exclusion": False,
"tools_drill_area_shape": "polygon",
"tools_drill_area_strategy": "over",
"tools_drill_area_overz": 1.0,
# NCC Tool
"tools_ncc_tools": "1.0, 0.5",
"tools_ncc_order": 'rev',
"tools_ncc_operation": 'clear',
"tools_ncc_overlap": 40,
"tools_ncc_margin": 1.0,
"tools_ncc_method": 1, # SEED
"tools_ncc_connect": True,
"tools_ncc_contour": True,
"tools_ncc_rest": False,
"tools_ncc_offset_choice": False,
"tools_ncc_offset_value": 0.0000,
"tools_ncc_ref": 0, # ITSELF
"tools_ncc_area_shape": "square",
"tools_ncc_milling_type": 'cl',
"tools_ncc_tool_type": 'C1',
"tools_ncc_cutz": -0.05,
"tools_ncc_tipdia": 0.1,
"tools_ncc_tipangle": 30,
"tools_ncc_newdia": 0.1,
"tools_ncc_plotting": 'normal',
"tools_ncc_check_valid": True,
# Cutout Tool
"tools_cutout_tooldia": 2.4,
"tools_cutout_kind": "single",
"tools_cutout_margin": 0.1,
"tools_cutout_z": -1.8,
"tools_cutout_depthperpass": 0.6,
"tools_cutout_mdepth": True,
"tools_cutout_gapsize": 4,
"tools_cutout_gaps_ff": "4",
"tools_cutout_convexshape": False,
"tools_cutout_big_cursor": True,
"tools_cutout_gap_type": 'b',
"tools_cutout_gap_depth": -1.0,
"tools_cutout_mb_dia": 0.6,
"tools_cutout_mb_spacing": 0.3,
# Paint Tool
"tools_paint_tooldia": 0.3,
"tools_paint_order": 'rev',
"tools_paint_overlap": 20,
"tools_paint_offset": 0.0,
"tools_paint_method": 0,
"tools_paint_selectmethod": 0,
"tools_paint_area_shape": "square",
"tools_paint_connect": True,
"tools_paint_contour": True,
"tools_paint_plotting": 'normal',
"tools_paint_rest": False,
"tools_paint_tool_type": 'C1',
"tools_paint_cutz": -0.05,
"tools_paint_tipdia": 0.1,
"tools_paint_tipangle": 30,
"tools_paint_newdia": 0.1,
# 2-Sided Tool
"tools_2sided_mirror_axis": "X",
"tools_2sided_axis_loc": "point",
"tools_2sided_drilldia": 3.125,
"tools_2sided_allign_axis": "X",
# Film Tool
"tools_film_type": 'neg',
"tools_film_boundary": 1.0,
"tools_film_scale_stroke": 0,
"tools_film_color": '#000000',
"tools_film_scale_cb": False,
"tools_film_scale_x_entry": 1.0,
"tools_film_scale_y_entry": 1.0,
"tools_film_skew_cb": False,
"tools_film_skew_x_entry": 0.0,
"tools_film_skew_y_entry": 0.0,
"tools_film_skew_ref_radio": 'bottomleft',
"tools_film_mirror_cb": False,
"tools_film_mirror_axis_radio": 'none',
"tools_film_file_type_radio": 'svg',
"tools_film_orientation": 'p',
"tools_film_pagesize": 'A4',
"tools_film_png_dpi": 96,
# Panel Tool
"tools_panelize_spacing_columns": 0.0,
"tools_panelize_spacing_rows": 0.0,
"tools_panelize_columns": 1,
"tools_panelize_rows": 1,
"tools_panelize_optimization": True,
"tools_panelize_constrain": False,
"tools_panelize_constrainx": 200.0,
"tools_panelize_constrainy": 290.0,
"tools_panelize_panel_type": 'gerber',
# Calculators Tool
"tools_calc_vshape_tip_dia": 0.2,
"tools_calc_vshape_tip_angle": 30,
"tools_calc_vshape_cut_z": 0.05,
"tools_calc_electro_length": 10.0,
"tools_calc_electro_width": 10.0,
"tools_calc_electro_area": 100.0,
"tools_calc_electro_cdensity": 13.0,
"tools_calc_electro_growth": 10.0,
# Transform Tool
"tools_transform_reference": _("Selection"),
"tools_transform_ref_object": _("Gerber"),
"tools_transform_ref_point": "0, 0",
"tools_transform_rotate": 90,
"tools_transform_skew_x": 0.0,
"tools_transform_skew_y": 0.0,
"tools_transform_skew_link": True,
"tools_transform_scale_x": 1.0,
"tools_transform_scale_y": 1.0,
"tools_transform_scale_link": True,
"tools_transform_offset_x": 0.0,
"tools_transform_offset_y": 0.0,
"tools_transform_buffer_dis": 0.0,
"tools_transform_buffer_factor": 100.0,
"tools_transform_buffer_corner": True,
# SolderPaste Tool
"tools_solderpaste_tools": "1.0, 0.3",
"tools_solderpaste_new": 0.3,
"tools_solderpaste_z_start": 0.05,
"tools_solderpaste_z_dispense": 0.1,
"tools_solderpaste_z_stop": 0.05,
"tools_solderpaste_z_travel": 0.1,
"tools_solderpaste_z_toolchange": 1.0,
"tools_solderpaste_xy_toolchange": "0.0, 0.0",
"tools_solderpaste_frxy": 150,
"tools_solderpaste_frz": 150,
"tools_solderpaste_frz_dispense": 1.0,
"tools_solderpaste_speedfwd": 300,
"tools_solderpaste_dwellfwd": 1,
"tools_solderpaste_speedrev": 200,
"tools_solderpaste_dwellrev": 1,
"tools_solderpaste_pp": 'Paste_1',
# Subtract Tool
"tools_sub_close_paths": True,
"tools_sub_delete_sources": False,
# Distance Tool
"tools_dist_snap_center": False,
# Corner Markers Tool
"tools_corners_thickness": 0.1,
"tools_corners_length": 3.0,
"tools_corners_margin": 0.0,
"tools_corners_type": 's',
"tools_corners_drill_dia": 0.5,
# ########################################################################################################
# ################################ TOOLS 2 ###############################################################
# ########################################################################################################
# Optimal Tool
"tools_opt_precision": 4,
# Check Rules Tool
"tools_cr_trace_size": True,
"tools_cr_trace_size_val": 0.25,
"tools_cr_c2c": True,
"tools_cr_c2c_val": 0.25,
"tools_cr_c2o": True,
"tools_cr_c2o_val": 1.0,
"tools_cr_s2s": True,
"tools_cr_s2s_val": 0.25,
"tools_cr_s2sm": True,
"tools_cr_s2sm_val": 0.25,
"tools_cr_s2o": True,
"tools_cr_s2o_val": 1.0,
"tools_cr_sm2sm": True,
"tools_cr_sm2sm_val": 0.25,
"tools_cr_ri": True,
"tools_cr_ri_val": 0.3,
"tools_cr_h2h": True,
"tools_cr_h2h_val": 0.3,
"tools_cr_dh": True,
"tools_cr_dh_val": 0.3,
# QRCode Tool
"tools_qrcode_version": 1,
"tools_qrcode_error": 'L',
"tools_qrcode_box_size": 3,
"tools_qrcode_border_size": 4,
"tools_qrcode_qrdata": '',
"tools_qrcode_polarity": 'pos',
"tools_qrcode_rounded": 's',
"tools_qrcode_fill_color": '#000000',
"tools_qrcode_back_color": '#FFFFFF',
"tools_qrcode_sel_limit": 330,
# Copper Thieving Tool
"tools_copper_thieving_clearance": 0.25,
"tools_copper_thieving_margin": 1.0,
"tools_copper_thieving_area": 0.1,
"tools_copper_thieving_reference": 'itself',
"tools_copper_thieving_box_type": 'rect',
"tools_copper_thieving_circle_steps": 64,
"tools_copper_thieving_fill_type": 'solid',
"tools_copper_thieving_dots_dia": 1.0,
"tools_copper_thieving_dots_spacing": 2.0,
"tools_copper_thieving_squares_size": 1.0,
"tools_copper_thieving_squares_spacing": 2.0,
"tools_copper_thieving_lines_size": 0.25,
"tools_copper_thieving_lines_spacing": 2.0,
"tools_copper_thieving_rb_margin": 1.0,
"tools_copper_thieving_rb_thickness": 1.0,
"tools_copper_thieving_mask_clearance": 0.0,
"tools_copper_thieving_geo_choice": 'b',
# Fiducials Tool
"tools_fiducials_dia": 1.0,
"tools_fiducials_margin": 1.0,
"tools_fiducials_mode": 'auto',
"tools_fiducials_second_pos": 'up',
"tools_fiducials_type": 'circular',
"tools_fiducials_line_thickness": 0.25,
# Calibration Tool
"tools_cal_calsource": 'object',
"tools_cal_travelz": 2.0,
"tools_cal_verz": 0.1,
"tools_cal_zeroz": False,
"tools_cal_toolchangez": 15,
"tools_cal_toolchange_xy": '',
"tools_cal_sec_point": 'tl',
# Drills Extraction Tool
"tools_edrills_hole_type": 'fixed',
"tools_edrills_hole_fixed_dia": 0.5,
"tools_edrills_hole_prop_factor": 80.0,
"tools_edrills_circular_ring": 0.2,
"tools_edrills_oblong_ring": 0.2,
"tools_edrills_square_ring": 0.2,
"tools_edrills_rectangular_ring": 0.2,
"tools_edrills_others_ring": 0.2,
"tools_edrills_circular": True,
"tools_edrills_oblong": False,
"tools_edrills_square": False,
"tools_edrills_rectangular": False,
"tools_edrills_others": False,
# Punch Gerber Tool
"tools_punch_hole_type": 'exc',
"tools_punch_hole_fixed_dia": 0.5,
"tools_punch_hole_prop_factor": 80.0,
"tools_punch_circular_ring": 0.2,
"tools_punch_oblong_ring": 0.2,
"tools_punch_square_ring": 0.2,
"tools_punch_rectangular_ring": 0.2,
"tools_punch_others_ring": 0.2,
"tools_punch_circular": True,
"tools_punch_oblong": False,
"tools_punch_square": True,
"tools_punch_rectangular": False,
"tools_punch_others": False,
# Align Objects Tool
"tools_align_objects_align_type": 'sp',
# Invert Gerber Tool
"tools_invert_margin": 0.1,
"tools_invert_join_style": 's',
# Utilities
# file associations
"fa_excellon": 'drd, drill, 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, ngc, out, ply, rol, sbp, tap, xpi',
"fa_gerber": 'art, bot, bsm, cmp, crc, crs, dim, gb0, gb1, gb2, gb3, gb4, 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, outline, pho, plc, pls, smb, smt, sol, spb, spt, ssb, sst, stc, sts, top, tsm',
# Keyword list
"util_autocomplete_keywords": 'Desktop, Documents, FlatConfig, FlatPrj, False, '
'Marius, My Documents, Paste_1, '
'Repetier, Roland_MDX_20, True, Users, Toolchange_Custom, '
'Toolchange_Probe_MACH3, '
'Toolchange_manual, Users, all, axis, auto, axisoffset, '
'box, center_x, center_y, columns, combine, connect, contour, default, '
'depthperpass, dia, diatol, dist, drilled_dias, drillz, dpp, dwelltime, '
'endxy, endz, extracut_length, f, feedrate, '
'feedrate_z, grbl_11, GRBL_laser, gridoffsety, gridx, gridy, has_offset, '
'holes, hpgl, iso_type, line_xyz, margin, marlin, method, milled_dias, '
'minoffset, name, offset, opt_type, order, outname, overlap, '
'passes, postamble, pp, ppname_e, ppname_g, preamble, radius, ref, rest, '
'rows, shellvar_, scale_factor, spacing_columns, spacing_rows, spindlespeed, '
'startz, startxy, toolchange_xy, toolchangez, '
'tooldia, travelz, use_threads, value, x, x0, x1, y, y0, y1, z_cut, '
'z_move',
"script_autocompleter": True,
"script_text": "",
"script_plot": True,
"script_source_file": "",
"document_autocompleter": False,
"document_text": "",
"document_plot": True,
"document_source_file": "",
"document_font_color": '#000000',
"document_sel_color": '#0055ff',
"document_font_size": 6,
"document_tab_size": 80,
}
@classmethod
def save_factory_defaults(cls, file_path: str, version: (float, str)):
"""Writes the factory defaults to a file at the given path, overwriting any existing file."""
# If the file exists
if os.path.isfile(file_path):
# tst if it is empty
with open(file_path, "r") as file:
f_defaults = simplejson.loads(file.read())
# if the file is not empty
if f_defaults:
# if it has the same version do nothing
if str(f_defaults['version']) == str(version):
return
# if the versions differ then remove the file
os.chmod(file_path, stat.S_IRWXO | stat.S_IWRITE | stat.S_IWGRP)
os.remove(file_path)
cls.factory_defaults['version'] = version
try:
# recreate a new factory defaults file and save the factory defaults data into it
f_f_def_s = open(file_path, "w")
simplejson.dump(cls.factory_defaults, f_f_def_s, default=to_dict, indent=2, sort_keys=True)
f_f_def_s.close()
# and then make the factory_defaults.FlatConfig file read_only
# so it can't be modified after creation.
os.chmod(file_path, stat.S_IREAD | stat.S_IRGRP | stat.S_IROTH)
log.debug("FlatCAM factory defaults written to: %s" % file_path)
except Exception as e:
log.error("save_factory_defaults() -> %s" % str(e))
def __init__(self, callback=lambda x: None, beta=True, version=8.9):
"""
:param callback: A method called each time that one of the values are changed in the self.defaults LouDict
"""
self.defaults = LoudDict()
self.beta = beta
self.version = version
self.factory_defaults['version'] = self.version
self.defaults.update(self.factory_defaults)
self.current_defaults = {} # copy used for restoring after cancelled prefs changes
self.current_defaults.update(self.factory_defaults)
self.old_defaults_found = False
self.defaults.set_change_callback(callback)
# #### Pass-through to the defaults LoudDict #####
def __len__(self):
return self.defaults.__len__()
def __getitem__(self, item):
return self.defaults.__getitem__(item)
def __setitem__(self, key, value):
return self.defaults.__setitem__(key, value)
def __delitem__(self, key):
return self.defaults.__delitem__(key)
def __iter__(self):
return self.defaults.__iter__()
def __getattr__(self, item):
# Unfortunately this method alone is not enough to pass through the other magic methods above.
return self.defaults.__getattribute__(item)
# #### Additional Methods #####
def write(self, filename: str):
"""Saves the defaults to a file on disk"""
with open(filename, "w") as file:
simplejson.dump(self.defaults, file, default=to_dict, indent=2, sort_keys=True)
def load(self, filename: str, inform):
"""
Loads the defaults from a file on disk, performing migration if required.
:param filename: a path to the file that is to be loaded
:param inform: a pyqtSignal used to display information's in the StatusBar of the GUI
"""
# Read in the file
try:
f = open(filename)
options = f.read()
f.close()
except IOError:
log.error("Could not load defaults file.")
inform.emit('[ERROR] %s' % _("Could not load the file."))
# in case the defaults file can't be loaded, show all toolbars
self.defaults["global_toolbar_view"] = 511
return
# Parse the JSON
try:
defaults = simplejson.loads(options)
except Exception:
# in case the defaults file can't be loaded, show all toolbars
self.defaults["global_toolbar_view"] = 511
e = sys.exc_info()[0]
log.error(str(e))
inform.emit('[ERROR] %s' % _("Failed to parse defaults file."))
return
if defaults is None:
return
# Perform migration if necessary but only if the defaults dict is not empty
if self.__is_old_defaults(defaults) and defaults:
self.old_defaults_found = True
# while the app is in Beta status, delete the older Preferences files
if self.beta is False:
log.debug("Found old preferences files. Migrating.")
defaults = self.__migrate_old_defaults(defaults=defaults)
# Save the resulting defaults
self.defaults.update(defaults)
self.current_defaults.update(self.defaults)
else:
log.debug("Found old preferences files. Resetting the files.")
# wipeout the old defaults
self.reset_to_factory_defaults()
else:
self.old_defaults_found = False
# Save the resulting defaults
self.defaults.update(defaults)
self.current_defaults.update(self.defaults)
log.debug("FlatCAM defaults loaded from: %s" % filename)
def __is_old_defaults(self, defaults: dict) -> bool:
"""Takes a defaults dict and determines whether or not migration is necessary."""
return 'version' not in defaults or defaults['version'] != self.factory_defaults['version']
def __migrate_old_defaults(self, defaults: dict) -> dict:
"""Performs migration on the passed-in defaults dictionary, and returns the migrated dict"""
migrated = {}
for k, v in defaults.items():
if k in self.factory_defaults and k != 'version':
# check if the types are the same. Because some types (tuple, float, int etc)
# may be stored as strings we check their types.
try:
target = eval(self.defaults[k])
except (NameError, TypeError, SyntaxError):
# it's an unknown string leave it as it is
target = deepcopy(self.factory_defaults[k])
try:
source = eval(v)
except (NameError, TypeError, SyntaxError):
# it's an unknown string leave it as it is
source = deepcopy(v)
if type(target) == type(source):
migrated[k] = v
return migrated
def reset_to_factory_defaults(self):
self.defaults.update(self.factory_defaults)
self.current_defaults.update(self.factory_defaults)
self.old_defaults_found = False
def propagate_defaults(self):
"""
This method is used to set default values in classes. It's
an alternative to project options but allows the use
of values invisible to the user.
"""
log.debug("propagate_defaults()")
# Which objects to update the given parameters.
routes = {
"global_zdownrate": CNCjob,
"excellon_zeros": Excellon,
"excellon_format_upper_in": Excellon,
"excellon_format_lower_in": Excellon,
"excellon_format_upper_mm": Excellon,
"excellon_format_lower_mm": Excellon,
"excellon_units": Excellon,
"gerber_use_buffer_for_union": Gerber,
"geometry_multidepth": Geometry
}
for param in routes:
if param in routes[param].defaults:
try:
routes[param].defaults[param] = self.defaults[param]
except KeyError:
log.error("FlatCAMApp.propagate_defaults() --> ERROR: " + param + " not in defaults.")
else:
# Try extracting the name:
# classname_param here is param in the object
if param.find(routes[param].__name__.lower() + "_") == 0:
p = param[len(routes[param].__name__) + 1:]
if p in routes[param].defaults:
routes[param].defaults[p] = self.defaults[param]
def report_usage(self, resource):
"""
Increments usage counter for the given resource
in self.defaults['global_stats'].
:param resource: Name of the resource.
:return: None
"""
if resource in self.defaults['global_stats']:
self.defaults['global_stats'][resource] += 1
else:
self.defaults['global_stats'][resource] = 1