You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

868 lines
39 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2020-2022 KiCad Developers, see AUTHORS.txt for contributors.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, you may find one here:
  18. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  19. * or you may search the http://www.gnu.org website for the version 2 license,
  20. * or you may write to the Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  22. */
  23. #include <pybind11/pybind11.h>
  24. #include <common.h>
  25. #include <footprint_editor_settings.h>
  26. #include <layer_ids.h>
  27. #include <pcbnew_settings.h>
  28. #include <pgm_base.h>
  29. #include <router/pns_routing_settings.h>
  30. #include <settings/common_settings.h>
  31. #include <settings/nested_settings.h>
  32. #include <settings/parameters.h>
  33. #include <settings/settings_manager.h>
  34. #include <wx/config.h>
  35. #include <wx/tokenzr.h>
  36. #include <zones.h>
  37. #include <widgets/ui_common.h>
  38. #include <base_units.h>
  39. #include "../3d-viewer/3d_viewer/eda_3d_viewer_settings.h"
  40. ///! Update the schema version whenever a migration is required
  41. const int pcbnewSchemaVersion = 2;
  42. PCBNEW_SETTINGS::PCBNEW_SETTINGS()
  43. : APP_SETTINGS_BASE( "pcbnew", pcbnewSchemaVersion ),
  44. m_AuiPanels(),
  45. m_Cleanup(),
  46. m_DrcDialog(),
  47. m_ExportIdf(),
  48. m_ExportStep(),
  49. m_ExportSvg(),
  50. m_ExportVrml(),
  51. m_FootprintWizardList(),
  52. m_GenDrill(),
  53. m_ImportGraphics(),
  54. m_NetlistDialog(),
  55. m_PlaceFile(),
  56. m_Plot(),
  57. m_FootprintChooser(),
  58. m_Zones(),
  59. m_FootprintViewer(),
  60. m_FootprintWizard(),
  61. m_Display(),
  62. m_TrackDragAction( TRACK_DRAG_ACTION::DRAG ),
  63. m_CtrlClickHighlight( false ),
  64. m_Use45DegreeLimit( false ),
  65. m_FlipLeftRight( false ),
  66. m_PolarCoords( false ),
  67. m_RotationAngle( ANGLE_90 ),
  68. m_ShowPageLimits( true ),
  69. m_AutoRefillZones( false ),
  70. m_AllowFreePads( false ),
  71. m_PnsSettings( nullptr ),
  72. m_FootprintViewerZoom( 1.0 ),
  73. m_FootprintViewerAutoZoomOnSelect( true )
  74. {
  75. m_MagneticItems.pads = MAGNETIC_OPTIONS::CAPTURE_CURSOR_IN_TRACK_TOOL;
  76. m_MagneticItems.tracks = MAGNETIC_OPTIONS::CAPTURE_CURSOR_IN_TRACK_TOOL;
  77. m_MagneticItems.graphics = false;
  78. m_params.emplace_back( new PARAM<bool>( "aui.show_layer_manager",
  79. &m_AuiPanels.show_layer_manager, true ) );
  80. m_params.emplace_back( new PARAM<int>( "aui.right_panel_width",
  81. &m_AuiPanels.right_panel_width, -1 ) );
  82. m_params.emplace_back( new PARAM<int>( "aui.appearance_panel_tab",
  83. &m_AuiPanels.appearance_panel_tab, 0, 0, 2 ) );
  84. m_params.emplace_back( new PARAM<int>( "footprint_chooser.width",
  85. &m_FootprintChooser.width, -1 ) );
  86. m_params.emplace_back( new PARAM<int>( "footprint_chooser.height",
  87. &m_FootprintChooser.height, -1 ) );
  88. m_params.emplace_back( new PARAM<int>( "footprint_chooser.sash_h",
  89. &m_FootprintChooser.sash_h, -1 ) );
  90. m_params.emplace_back( new PARAM<int>( "footprint_chooser.sash_v",
  91. &m_FootprintChooser.sash_v, -1 ) );
  92. m_params.emplace_back( new PARAM<bool>( "editing.flip_left_right",
  93. &m_FlipLeftRight, true ) );
  94. m_params.emplace_back( new PARAM<bool>( "editing.magnetic_graphics",
  95. &m_MagneticItems.graphics, true ) );
  96. m_params.emplace_back( new PARAM<int>( "editing.magnetic_pads",
  97. reinterpret_cast<int*>( &m_MagneticItems.pads ),
  98. static_cast<int>( MAGNETIC_OPTIONS::CAPTURE_CURSOR_IN_TRACK_TOOL ) ) );
  99. m_params.emplace_back( new PARAM<int>( "editing.magnetic_tracks",
  100. reinterpret_cast<int*>( &m_MagneticItems.tracks ),
  101. static_cast<int>( MAGNETIC_OPTIONS::CAPTURE_CURSOR_IN_TRACK_TOOL ) ) );
  102. m_params.emplace_back( new PARAM<bool>( "editing.polar_coords",
  103. &m_PolarCoords, false ) );
  104. m_params.emplace_back( new PARAM<int>( "editing.track_drag_action",
  105. reinterpret_cast<int*>( &m_TrackDragAction ),
  106. static_cast<int>( TRACK_DRAG_ACTION::DRAG ) ) );
  107. m_params.emplace_back( new PARAM<bool>( "editing.ctrl_click_highlight",
  108. &m_CtrlClickHighlight, false ) );
  109. m_params.emplace_back( new PARAM<bool>( "editing.pcb_use_45_degree_limit",
  110. &m_Use45DegreeLimit, false ) );
  111. m_params.emplace_back( new PARAM<bool>( "editing.auto_fill_zones",
  112. &m_AutoRefillZones, false ) );
  113. m_params.emplace_back( new PARAM<bool>( "editing.allow_free_pads",
  114. &m_AllowFreePads, false ) );
  115. m_params.emplace_back( new PARAM_LAMBDA<int>( "editing.rotation_angle",
  116. [this] () -> int
  117. {
  118. int rot = m_RotationAngle.AsTenthsOfADegree();
  119. // Don't store values larger than 360 degrees
  120. return rot % 3600;
  121. },
  122. [this] ( int aVal )
  123. {
  124. if( aVal )
  125. m_RotationAngle = EDA_ANGLE( aVal, TENTHS_OF_A_DEGREE_T );
  126. // A misconfiguration allowed some angles to be stored as tenth of a degree but read
  127. // as tens of degrees. By disallowing storage of values larger than 360, we can weed out
  128. // those invalid values here.
  129. while( m_RotationAngle > ANGLE_360 )
  130. m_RotationAngle = m_RotationAngle / 100;
  131. },
  132. 900 ) );
  133. m_params.emplace_back( new PARAM<bool>( "pcb_display.graphic_items_fill",
  134. &m_Display.m_DisplayGraphicsFill, true ) );
  135. m_params.emplace_back( new PARAM<int>( "pcb_display.max_links_shown",
  136. &m_Display.m_MaxLinksShowed, 3, 0, 15 ) );
  137. m_params.emplace_back( new PARAM<bool>( "pcb_display.graphics_fill",
  138. &m_Display.m_DisplayGraphicsFill, true ) );
  139. m_params.emplace_back( new PARAM<bool>( "pcb_display.text_fill",
  140. &m_Display.m_DisplayTextFill, true ) );
  141. m_params.emplace_back( new PARAM<int>( "pcb_display.net_names_mode",
  142. &m_Display.m_NetNames, 3, 0, 3 ) );
  143. m_params.emplace_back( new PARAM<bool>( "pcb_display.pad_clearance",
  144. &m_Display.m_PadClearance, true ) );
  145. m_params.emplace_back( new PARAM<bool>( "pcb_display.pad_no_connects",
  146. &m_Display.m_PadNoConnects, true ) );
  147. m_params.emplace_back( new PARAM<bool>( "pcb_display.pad_fill",
  148. &m_Display.m_DisplayPadFill, true ) );
  149. m_params.emplace_back( new PARAM<bool>( "pcb_display.pad_numbers",
  150. &m_Display.m_PadNumbers, true ) );
  151. m_params.emplace_back( new PARAM<bool>( "pcb_display.ratsnest_global",
  152. &m_Display.m_ShowGlobalRatsnest, true ) );
  153. m_params.emplace_back( new PARAM<bool>( "pcb_display.ratsnest_footprint",
  154. &m_Display.m_ShowModuleRatsnest, true ) );
  155. m_params.emplace_back( new PARAM<bool>( "pcb_display.ratsnest_curved",
  156. &m_Display.m_DisplayRatsnestLinesCurved, false ) );
  157. m_params.emplace_back( new PARAM<int>( "pcb_display.track_clearance_mode",
  158. reinterpret_cast<int*>( &m_Display.m_TrackClearance ), SHOW_WITH_VIA_WHILE_ROUTING ) );
  159. m_params.emplace_back( new PARAM<bool>( "pcb_display.track_fill",
  160. &m_Display.m_DisplayPcbTrackFill, true ) );
  161. m_params.emplace_back( new PARAM<bool>( "pcb_display.via_fill",
  162. &m_Display.m_DisplayViaFill, true ) );
  163. m_params.emplace_back( new PARAM<int>( "pcb_display.origin_mode",
  164. reinterpret_cast<int*>( &m_Display.m_DisplayOrigin ),
  165. PCB_DISPLAY_ORIGIN::PCB_ORIGIN_PAGE ) );
  166. m_params.emplace_back( new PARAM<bool>( "pcb_display.origin_invert_x_axis",
  167. &m_Display.m_DisplayInvertXAxis, false ) );
  168. m_params.emplace_back( new PARAM<bool>( "pcb_display.origin_invert_y_axis",
  169. &m_Display.m_DisplayInvertYAxis, false ) );
  170. m_params.emplace_back( new PARAM<bool>( "pcb_display.live_3d_refresh",
  171. &m_Display.m_Live3DRefresh, false ) );
  172. m_params.emplace_back( new PARAM<bool>( "pcb_display.show_page_borders",
  173. &m_ShowPageLimits, true ) );
  174. m_params.emplace_back( new PARAM<bool>( "cleanup.cleanup_vias",
  175. &m_Cleanup.cleanup_vias, true ) );
  176. m_params.emplace_back( new PARAM<bool>( "cleanup.delete_dangling_vias",
  177. &m_Cleanup.delete_dangling_vias, true ) );
  178. m_params.emplace_back( new PARAM<bool>( "cleanup.merge_segments",
  179. &m_Cleanup.merge_segments, true ) );
  180. m_params.emplace_back( new PARAM<bool>( "cleanup.cleanup_unconnected",
  181. &m_Cleanup.cleanup_unconnected, true ) );
  182. m_params.emplace_back( new PARAM<bool>( "cleanup.cleanup_short_circuits",
  183. &m_Cleanup.cleanup_short_circuits, true ) );
  184. m_params.emplace_back( new PARAM<bool>( "cleanup.cleanup_tracks_in_pad",
  185. &m_Cleanup.cleanup_tracks_in_pad, false ) );
  186. m_params.emplace_back( new PARAM<bool>( "drc_dialog.refill_zones",
  187. &m_DrcDialog.refill_zones, true ) );
  188. m_params.emplace_back( new PARAM<bool>( "drc_dialog.test_all_track_errors",
  189. &m_DrcDialog.test_all_track_errors, false ) );
  190. m_params.emplace_back( new PARAM<bool>( "drc_dialog.test_footprints",
  191. &m_DrcDialog.test_footprints, false ) );
  192. m_params.emplace_back( new PARAM<int>( "drc_dialog.severities",
  193. &m_DrcDialog.severities, RPT_SEVERITY_ERROR | RPT_SEVERITY_WARNING ) );
  194. m_params.emplace_back( new PARAM<bool>( "gen_drill.merge_pth_npth",
  195. &m_GenDrill.merge_pth_npth, false ) );
  196. m_params.emplace_back( new PARAM<bool>( "gen_drill.minimal_header",
  197. &m_GenDrill.minimal_header, false ) );
  198. m_params.emplace_back( new PARAM<bool>( "gen_drill.mirror",
  199. &m_GenDrill.mirror, false ) );
  200. m_params.emplace_back( new PARAM<bool>( "gen_drill.unit_drill_is_inch",
  201. &m_GenDrill.unit_drill_is_inch, true ) );
  202. m_params.emplace_back( new PARAM<bool>( "gen_drill.use_route_for_oval_holes",
  203. &m_GenDrill.use_route_for_oval_holes, true ) );
  204. m_params.emplace_back( new PARAM<int>( "gen_drill.drill_file_type",
  205. &m_GenDrill.drill_file_type, 0 ) );
  206. m_params.emplace_back( new PARAM<int>( "gen_drill.map_file_type",
  207. &m_GenDrill.map_file_type, 1 ) );
  208. m_params.emplace_back( new PARAM<int>( "gen_drill.zeros_format",
  209. &m_GenDrill.zeros_format, 0, 0, 3 ) );
  210. m_params.emplace_back( new PARAM<bool>( "export_idf.auto_adjust",
  211. &m_ExportIdf.auto_adjust, false ) );
  212. m_params.emplace_back( new PARAM<int>( "export_idf.ref_units",
  213. &m_ExportIdf.ref_units, 0 ) );
  214. m_params.emplace_back( new PARAM<double>( "export_idf.ref_x",
  215. &m_ExportIdf.ref_x, 0 ) );
  216. m_params.emplace_back( new PARAM<double>( "export_idf.ref_y",
  217. &m_ExportIdf.ref_y, 0 ) );
  218. m_params.emplace_back( new PARAM<bool>( "export_idf.units_mils",
  219. &m_ExportIdf.units_mils, false ) );
  220. m_params.emplace_back( new PARAM<int>( "export_step.origin_mode",
  221. &m_ExportStep.origin_mode, 0 ) );
  222. m_params.emplace_back( new PARAM<int>( "export_step.origin_units",
  223. &m_ExportStep.origin_units, 0 ) );
  224. m_params.emplace_back( new PARAM<double>( "export_step.origin_x",
  225. &m_ExportStep.origin_x, 0 ) );
  226. m_params.emplace_back( new PARAM<double>( "export_step.origin_y",
  227. &m_ExportStep.origin_y, 0 ) );
  228. m_params.emplace_back( new PARAM<bool>( "export_step.no_virtual",
  229. &m_ExportStep.no_virtual, false ) );
  230. m_params.emplace_back( new PARAM<bool>( "export_step.replace_models",
  231. &m_ExportStep.replace_models, false ) );
  232. m_params.emplace_back( new PARAM<bool>( "export_step.overwrite_file",
  233. &m_ExportStep.overwrite_file, true ) );
  234. m_params.emplace_back( new PARAM<bool>( "export_svg.black_and_white",
  235. &m_ExportSvg.black_and_white, false ) );
  236. m_params.emplace_back( new PARAM<bool>( "export_svg.mirror",
  237. &m_ExportSvg.mirror, false ) );
  238. m_params.emplace_back( new PARAM<bool>( "export_svg.one_file",
  239. &m_ExportSvg.one_file, false ) );
  240. m_params.emplace_back(new PARAM<bool>( "export_svg.plot_board_edges",
  241. &m_ExportSvg.plot_board_edges, true ) );
  242. m_params.emplace_back( new PARAM<int>( "export_svg.page_size",
  243. &m_ExportSvg.page_size, 0 ) );
  244. m_params.emplace_back( new PARAM<wxString>( "export_svg.output_dir",
  245. &m_ExportSvg.output_dir, "" ) );
  246. m_params.emplace_back( new PARAM_LIST<int>( "export_svg.layers",
  247. &m_ExportSvg.layers, {} ) );
  248. m_params.emplace_back( new PARAM<int>( "export_vrml.units",
  249. &m_ExportVrml.units, 1 ) );
  250. m_params.emplace_back( new PARAM<bool>( "export_vrml.copy_3d_models",
  251. &m_ExportVrml.copy_3d_models, false ) );
  252. m_params.emplace_back( new PARAM<bool>( "export_vrml.use_relative_paths",
  253. &m_ExportVrml.use_relative_paths, false ) );
  254. m_params.emplace_back( new PARAM<int>( "export_vrml.ref_units",
  255. &m_ExportVrml.ref_units, 0 ) );
  256. m_params.emplace_back( new PARAM<double>( "export_vrml.ref_x",
  257. &m_ExportVrml.ref_x, 0 ) );
  258. m_params.emplace_back( new PARAM<double>( "export_vrml.ref_y",
  259. &m_ExportVrml.ref_y, 0 ) );
  260. m_params.emplace_back( new PARAM<int>( "export_vrml.origin_mode",
  261. &m_ExportVrml.origin_mode, 0 ) );
  262. m_params.emplace_back( new PARAM<int>( "zones.hatching_style",
  263. &m_Zones.hatching_style, 0 ) );
  264. m_params.emplace_back( new PARAM<int>( "zones.net_sort_mode",
  265. &m_Zones.net_sort_mode, -1 ) );
  266. m_params.emplace_back( new PARAM<double>( "zones.clearance",
  267. &m_Zones.clearance, ZONE_CLEARANCE_MIL ) );
  268. m_params.emplace_back( new PARAM<double>( "zones.min_thickness",
  269. &m_Zones.min_thickness, ZONE_THICKNESS_MIL ) );
  270. m_params.emplace_back( new PARAM<double>( "zones.thermal_relief_gap",
  271. &m_Zones.thermal_relief_gap, ZONE_THERMAL_RELIEF_GAP_MIL ) );
  272. m_params.emplace_back( new PARAM<double>( "zones.thermal_relief_copper_width",
  273. &m_Zones.thermal_relief_copper_width, ZONE_THERMAL_RELIEF_COPPER_WIDTH_MIL ) );
  274. m_params.emplace_back( new PARAM<int>( "import_graphics.layer",
  275. &m_ImportGraphics.layer, Dwgs_User ) );
  276. m_params.emplace_back( new PARAM<bool>( "import_graphics.interactive_placement",
  277. &m_ImportGraphics.interactive_placement, true ) );
  278. m_params.emplace_back( new PARAM<int>( "import_graphics.line_width_units",
  279. &m_ImportGraphics.line_width_units, 0 ) );
  280. m_params.emplace_back( new PARAM<double>( "import_graphics.line_width",
  281. &m_ImportGraphics.line_width, 0.2 ) );
  282. m_params.emplace_back( new PARAM<int>( "import_graphics.origin_units",
  283. &m_ImportGraphics.origin_units, 0 ) );
  284. m_params.emplace_back( new PARAM<double>( "import_graphics.origin_x",
  285. &m_ImportGraphics.origin_x, 0 ) );
  286. m_params.emplace_back( new PARAM<double>( "import_graphics.origin_y",
  287. &m_ImportGraphics.origin_y, 0 ) );
  288. m_params.emplace_back( new PARAM<int>( "import_graphics.dxf_units",
  289. &m_ImportGraphics.dxf_units, 0 ) );
  290. m_params.emplace_back( new PARAM<int>( "netlist.report_filter",
  291. &m_NetlistDialog.report_filter, -1 ) );
  292. m_params.emplace_back( new PARAM<bool>( "netlist.update_footprints",
  293. &m_NetlistDialog.update_footprints, true ) );
  294. m_params.emplace_back( new PARAM<bool>( "netlist.delete_shorting_tracks",
  295. &m_NetlistDialog.delete_shorting_tracks, false ) );
  296. m_params.emplace_back( new PARAM<bool>( "netlist.delete_extra_footprints",
  297. &m_NetlistDialog.delete_extra_footprints, false ) );
  298. m_params.emplace_back( new PARAM<bool>( "netlist.associate_by_ref_sch",
  299. &m_NetlistDialog.associate_by_ref_sch, false ) );
  300. m_params.emplace_back(new PARAM<int>( "place_file.units",
  301. &m_PlaceFile.units, 1 ) );
  302. m_params.emplace_back( new PARAM<int>( "place_file.file_options",
  303. &m_PlaceFile.file_options, 0 ) );
  304. m_params.emplace_back( new PARAM<int>( "place_file.file_format",
  305. &m_PlaceFile.file_format, 0 ) );
  306. m_params.emplace_back( new PARAM<bool>( "place_file.include_board_edge",
  307. &m_PlaceFile.include_board_edge, false ) );
  308. m_params.emplace_back( new PARAM<bool>( "place_file.use_place_file_origin",
  309. &m_PlaceFile.use_aux_origin, true ) );
  310. m_params.emplace_back( new PARAM<int>( "plot.all_layers_on_one_page",
  311. &m_Plot.all_layers_on_one_page, 1 ) );
  312. m_params.emplace_back( new PARAM<bool>( "plot.edgecut_on_all_layers",
  313. &m_Plot.edgecut_on_all_layers, true ) );
  314. m_params.emplace_back( new PARAM<int>( "plot.pads_drill_mode",
  315. &m_Plot.pads_drill_mode, 2 ) );
  316. m_params.emplace_back( new PARAM<double>( "plot.fine_scale_x",
  317. &m_Plot.fine_scale_x, 0 ) );
  318. m_params.emplace_back( new PARAM<double>( "plot.fine_scale_y",
  319. &m_Plot.fine_scale_y, 0 ) );
  320. m_params.emplace_back( new PARAM<double>( "plot.ps_fine_width_adjust",
  321. &m_Plot.ps_fine_width_adjust, 0 ) );
  322. m_params.emplace_back( new PARAM<bool>( "plot.check_zones_before_plotting",
  323. &m_Plot.check_zones_before_plotting, true ) );
  324. m_params.emplace_back( new PARAM<bool>( "plot.mirror",
  325. &m_Plot.mirror, false ) );
  326. m_params.emplace_back( new PARAM<wxString>( "window.footprint_text_shown_columns",
  327. &m_FootprintTextShownColumns, "0 1 2 3 4 5 6" ) );
  328. m_params.emplace_back( new PARAM<int>( "footprint_wizard_list.width",
  329. &m_FootprintWizardList.width, -1 ) );
  330. m_params.emplace_back( new PARAM<int>( "footprint_wizard_list.height",
  331. &m_FootprintWizardList.height, -1 ) );
  332. m_params.emplace_back( new PARAM<bool>( "reannotate_dialog.annotate_sort_on_modules",
  333. &m_Reannotate.sort_on_fp_location, true ) );
  334. m_params.emplace_back( new PARAM<bool>( "reannotate_dialog.annotate_remove_front_prefix",
  335. &m_Reannotate.remove_front_prefix, false ) );
  336. m_params.emplace_back( new PARAM<bool>( "reannotate_dialog.annotate_remove_back_prefix",
  337. &m_Reannotate.remove_back_prefix, false ) );
  338. m_params.emplace_back( new PARAM<bool>( "reannotate_dialog.annotate_exclude_locked",
  339. &m_Reannotate.exclude_locked, false ) );
  340. m_params.emplace_back( new PARAM<int>( "reannotate_dialog.annotate_grid_index",
  341. &m_Reannotate.grid_index, 0 ) );
  342. m_params.emplace_back( new PARAM<int>( "reannotate_dialog.annotate_sort_code",
  343. &m_Reannotate.sort_code, 0 ) );
  344. m_params.emplace_back( new PARAM<int>( "reannotate_dialog.annotate_choice",
  345. &m_Reannotate.annotation_choice, 0 ) );
  346. m_params.emplace_back( new PARAM<int>( "reannotate_dialog.annotate_report_severity",
  347. &m_Reannotate.report_severity, 0 ) );
  348. m_params.emplace_back( new PARAM<wxString>( "reannotate_dialog.annotate_front_refdes_start",
  349. &m_Reannotate.front_refdes_start, "1" ) );
  350. m_params.emplace_back( new PARAM<wxString>( "reannotate_dialog.annotate_back_refdes_start",
  351. &m_Reannotate.back_refdes_start, "" ) );
  352. m_params.emplace_back( new PARAM<wxString>( "reannotate_dialog.annotate_front_prefix",
  353. &m_Reannotate.front_prefix, "" ) );
  354. m_params.emplace_back( new PARAM<wxString>( "reannotate_dialog.annotate_back_prefix",
  355. &m_Reannotate.back_prefix, "" ) );
  356. m_params.emplace_back( new PARAM<wxString>( "reannotate_dialog.annotate_exclude_list",
  357. &m_Reannotate.exclude_list, "" ) );
  358. m_params.emplace_back( new PARAM<wxString>( "reannotate_dialog.annotate_report_file_name",
  359. &m_Reannotate.report_file_name, "" ) );
  360. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "action_plugins",
  361. [&]() -> nlohmann::json
  362. {
  363. nlohmann::json js = nlohmann::json::array();
  364. for( const auto& pair : m_VisibleActionPlugins )
  365. js.push_back( nlohmann::json( { { pair.first.ToUTF8(), pair.second } } ) );
  366. return js;
  367. },
  368. [&]( const nlohmann::json& aObj )
  369. {
  370. m_VisibleActionPlugins.clear();
  371. if( !aObj.is_array() )
  372. {
  373. return;
  374. }
  375. for( const auto& entry : aObj )
  376. {
  377. if( entry.empty() || !entry.is_object() )
  378. continue;
  379. for( const auto& pair : entry.items() )
  380. {
  381. m_VisibleActionPlugins.emplace_back( std::make_pair(
  382. wxString( pair.key().c_str(), wxConvUTF8 ), pair.value() ) );
  383. }
  384. }
  385. },
  386. nlohmann::json::array() ) );
  387. addParamsForWindow( &m_FootprintViewer, "footprint_viewer" );
  388. m_params.emplace_back( new PARAM<double>( "footprint_viewer.zoom",
  389. &m_FootprintViewerZoom, 1.0 ) );
  390. m_params.emplace_back( new PARAM<bool>( "footprint_viewer.autozoom",
  391. &m_FootprintViewerAutoZoomOnSelect, true ) );
  392. addParamsForWindow( &m_FootprintWizard, "footprint_wizard" );
  393. m_params.emplace_back( new PARAM<wxString>( "system.last_footprint_lib_dir",
  394. &m_lastFootprintLibDir, "" ) );
  395. m_params.emplace_back( new PARAM<wxString>( "system.last_footprint3d_dir",
  396. &m_lastFootprint3dDir, "" ) );
  397. registerMigration( 0, 1,
  398. [&]()
  399. {
  400. if( OPT<int> optval = Get<int>( "pcb_display.rotation_angle" ) )
  401. Set( "editing.rotation_angle", optval.get() );
  402. try
  403. {
  404. At( "pcb_display" ).erase( "rotation_angle" );
  405. }
  406. catch( ... )
  407. {}
  408. return true;
  409. } );
  410. registerMigration( 1, 2,
  411. [&]()
  412. {
  413. // In version 1 this meant "after Zone Properties dialog", but it now means
  414. // "everywhere" so we knock it off on transition.
  415. Set( "editing.auto_fill_zones", false );
  416. return true;
  417. } );
  418. }
  419. PCBNEW_SETTINGS::~PCBNEW_SETTINGS() = default;
  420. bool PCBNEW_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
  421. {
  422. bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
  423. const std::string f = getLegacyFrameName();
  424. //
  425. // NOTE: there's no value in line-wrapping these; it just makes the table unreadable.
  426. //
  427. ret &= fromLegacy<bool>( aCfg, "ShowLayerManagerTools", "aui.show_layer_manager" );
  428. ret &= fromLegacy<int>( aCfg, "FootprintChooserHSashPosition", "footprint_chooser.sash_h" );
  429. ret &= fromLegacy<int>( aCfg, "FootprintChooserVSashPosition", "footprint_chooser.sash_v" );
  430. ret &= fromLegacy<int>( aCfg, "FootprintChooserWidth", "footprint_chooser.width" );
  431. ret &= fromLegacy<int>( aCfg, "FootprintChooserHeight", "footprint_chooser.height" );
  432. ret &= fromLegacy<bool>( aCfg, "FlipLeftRight", "editing.flip_left_right" );
  433. ret &= fromLegacy<bool>( aCfg, "MagneticGraphics", "editing.magnetic_graphics" );
  434. ret &= fromLegacy<int>( aCfg, "MagneticPads", "editing.magnetic_pads" );
  435. ret &= fromLegacy<int>( aCfg, "MagneticTracks", "editing.magnetic_tracks" );
  436. ret &= fromLegacy<bool>( aCfg, "DisplayPolarCoords", "editing.polar_coords" );
  437. ret &= fromLegacy<bool>( aCfg, "Use45DegreeGraphicSegments", "editing.use_45_degree_graphic_segments" );
  438. ret &= fromLegacy<bool>( aCfg, "PcbAffT", "pcb_display.graphic_items_fill" );
  439. ret &= fromLegacy<int>( aCfg, "MaxLnkS", "pcb_display.max_links_shown" );
  440. ret &= fromLegacy<bool>( aCfg, "ModAffC", "pcb_display.footprint_edge_fill" );
  441. ret &= fromLegacy<bool>( aCfg, "ModAffT", "pcb_display.footprint_text_fill" );
  442. ret &= fromLegacy<int>( aCfg, "ShowNetNamesMode", "pcb_display.net_names_mode" );
  443. ret &= fromLegacy<int>( aCfg, "PcbDisplayOrigin", "pcb_display.origin_mode" );
  444. ret &= fromLegacy<bool>( aCfg, "PcbInvertXAxis", "pcb_display.origin_invert_x_axis" );
  445. ret &= fromLegacy<bool>( aCfg, "PcbInvertYAxis", "pcb_display.origin_invert_y_axis" );
  446. ret &= fromLegacy<bool>( aCfg, "PadAffG", "pcb_display.pad_clearance" );
  447. ret &= fromLegacy<bool>( aCfg, "PadFill", "pcb_display.pad_fill" );
  448. ret &= fromLegacy<bool>( aCfg, "PadSNum", "pcb_display.pad_numbers" );
  449. ret &= fromLegacy<bool>( aCfg, "ShowRatsnestLines", "pcb_display.ratsnest_global" );
  450. ret &= fromLegacy<bool>( aCfg, "ShowRatsnestModuleLines", "pcb_display.ratsnest_footprint" );
  451. ret &= fromLegacy<bool>( aCfg, "CurvedRatsnestLines", "pcb_display.ratsnest_curved" );
  452. ret &= fromLegacy<int>( aCfg, "RotationAngle", "pcb_display.rotation_angle" );
  453. ret &= fromLegacy<int>( aCfg, "TrackDisplayClearance", "pcb_display.track_clearance_mode" );
  454. ret &= fromLegacy<bool>( aCfg, "DisplayTrackFilled", "pcb_display.track_fill" );
  455. ret &= fromLegacy<bool>( aCfg, "ViaFill", "pcb_display.via_fill" );
  456. ret &= fromLegacy<int>( aCfg, "PcbShowZonesMode", "pcb_display.zone_mode" );
  457. ret &= fromLegacy<double>( aCfg, "PlotLineWidth_mm", "plot.line_width" );
  458. aCfg->SetPath( "/dialogs/cleanup_tracks" );
  459. ret &= fromLegacy<bool>( aCfg, "DialogCleanupVias", "cleanup.cleanup_vias" );
  460. ret &= fromLegacy<bool>( aCfg, "DialogCleanupMergeSegments", "cleanup.merge_segments" );
  461. ret &= fromLegacy<bool>( aCfg, "DialogCleanupUnconnected", "cleanup.cleanup_unconnected" );
  462. ret &= fromLegacy<bool>( aCfg, "DialogCleanupShortCircuit", "cleanup.cleanup_short_circuits" );
  463. ret &= fromLegacy<bool>( aCfg, "DialogCleanupTracksInPads", "cleanup.cleanup_tracks_in_pad" );
  464. aCfg->SetPath( "../.." );
  465. ret &= fromLegacy<bool>( aCfg, "RefillZonesBeforeDrc", "drc_dialog.refill_zones" );
  466. ret &= fromLegacy<bool>( aCfg, "DrcTestFootprints", "drc_dialog.test_footprints" );
  467. ret &= fromLegacy<bool>( aCfg, "DrillMergePTHNPTH", "gen_drill.merge_pth_npth" );
  468. ret &= fromLegacy<bool>( aCfg, "DrillMinHeader", "gen_drill.minimal_header" );
  469. ret &= fromLegacy<bool>( aCfg, "DrillMirrorYOpt", "gen_drill.mirror" );
  470. ret &= fromLegacy<bool>( aCfg, "DrillUnit", "gen_drill.unit_drill_is_inch" );
  471. ret &= fromLegacy<bool>( aCfg, "OvalHolesRouteMode", "gen_drill.use_route_for_oval_holes" );
  472. ret &= fromLegacy<int>( aCfg, "DrillFileType", "gen_drill.drill_file_type" );
  473. ret &= fromLegacy<int>( aCfg, "DrillMapFileType", "gen_drill.map_file_type" );
  474. ret &= fromLegacy<int>( aCfg, "DrillZerosFormat", "gen_drill.zeros_format" );
  475. ret &= fromLegacy<bool>( aCfg, "IDFRefAutoAdj", "export_idf.auto_adjust" );
  476. ret &= fromLegacy<int>( aCfg, "IDFRefUnits", "export_idf.ref_units" );
  477. ret &= fromLegacy<double>( aCfg, "IDFRefX", "export_idf.ref_x" );
  478. ret &= fromLegacy<double>( aCfg, "IDFRefY", "export_idf.ref_y" );
  479. ret &= fromLegacy<bool>( aCfg, "IDFExportThou", "export_idf.units_mils" );
  480. ret &= fromLegacy<int>( aCfg, "STEP_Origin_Opt", "export_step.origin_mode" );
  481. ret &= fromLegacy<int>( aCfg, "STEP_UserOriginUnits", "export_step.origin_units" );
  482. ret &= fromLegacy<double>( aCfg, "STEP_UserOriginX", "export_step.origin_x" );
  483. ret &= fromLegacy<double>( aCfg, "STEP_UserOriginY", "export_step.origin_y" );
  484. ret &= fromLegacy<bool>( aCfg, "STEP_NoVirtual", "export_step.no_virtual" );
  485. ret &= fromLegacy<bool>( aCfg, "PlotSVGModeColor", "export_svg.black_and_white" );
  486. ret &= fromLegacy<bool>( aCfg, "PlotSVGModeMirror", "export_svg.mirror" );
  487. ret &= fromLegacy<bool>( aCfg, "PlotSVGModeOneFile", "export_svg.one_file" );
  488. ret &= fromLegacy<bool>( aCfg, "PlotSVGBrdEdge", "export_svg.plot_board_edges" );
  489. ret &= fromLegacy<int>( aCfg, "PlotSVGPageOpt", "export_svg.page_size" );
  490. ret &= fromLegacyString( aCfg, "PlotSVGDirectory", "export_svg.output_dir" );
  491. {
  492. nlohmann::json js = nlohmann::json::array();
  493. wxString key;
  494. bool val = false;
  495. for( unsigned i = 0; i < PCB_LAYER_ID_COUNT; ++i )
  496. {
  497. key.Printf( wxT( "PlotSVGLayer_%d" ), i );
  498. if( aCfg->Read( key, &val ) && val )
  499. js.push_back( i );
  500. }
  501. Set( "export_svg.layers", js );
  502. }
  503. {
  504. nlohmann::json js = nlohmann::json::array();
  505. wxString packed;
  506. if( aCfg->Read( "ActionPluginButtons", &packed ) )
  507. {
  508. wxStringTokenizer pluginSettingsTokenizer = wxStringTokenizer( packed, ";" );
  509. while( pluginSettingsTokenizer.HasMoreTokens() )
  510. {
  511. nlohmann::json row;
  512. wxString plugin = pluginSettingsTokenizer.GetNextToken();
  513. wxStringTokenizer pluginTokenizer = wxStringTokenizer( plugin, "=" );
  514. if( pluginTokenizer.CountTokens() != 2 )
  515. {
  516. // Bad config
  517. continue;
  518. }
  519. std::string key( pluginTokenizer.GetNextToken().ToUTF8() );
  520. bool value( pluginTokenizer.GetNextToken().Cmp( wxT( "Visible" ) ) == 0 );
  521. js.push_back( nlohmann::json( { { key, value } } ) );
  522. }
  523. }
  524. Set( "action_plugins", js );
  525. }
  526. //
  527. // NOTE: there's no value in line-wrapping these; it just makes the table unreadable.
  528. //
  529. ret &= fromLegacy<int>( aCfg, "VrmlExportUnit", "export_vrml.units" );
  530. ret &= fromLegacy<bool>( aCfg, "VrmlExportCopyFiles", "export_vrml.copy_3d_models" );
  531. ret &= fromLegacy<bool>( aCfg, "VrmlUseRelativePaths", "export_vrml.use_relative_paths" );
  532. ret &= fromLegacy<int>( aCfg, "VrmlRefUnits", "export_vrml.ref_units" );
  533. ret &= fromLegacy<double>( aCfg, "VrmlRefX", "export_vrml.ref_x" );
  534. ret &= fromLegacy<double>( aCfg, "VrmlRefY", "export_vrml.ref_y" );
  535. ret &= fromLegacy<int> ( aCfg, "VrmlOriginMode", "export_vrml.origin_mode" );
  536. ret &= fromLegacy<int>( aCfg, "Zone_Ouline_Hatch_Opt", "zones.hatching_style" );
  537. ret &= fromLegacy<int>( aCfg, "Zone_NetSort_Opt", "zones.net_sort_mode" );
  538. ret &= fromLegacy<double>( aCfg, "Zone_Clearance", "zones.clearance" );
  539. ret &= fromLegacy<double>( aCfg, "Zone_Thickness", "zones.min_thickness" );
  540. ret &= fromLegacy<double>( aCfg, "Zone_TH_Gap", "zones.thermal_relief_gap" );
  541. ret &= fromLegacy<double>( aCfg, "Zone_TH_Copper_Width", "zones.thermal_relief_copper_width" );
  542. aCfg->SetPath( "ImportGraphics" );
  543. ret &= fromLegacy<int>( aCfg, "BoardLayer", "import_graphics.layer" );
  544. ret &= fromLegacy<bool>( aCfg, "InteractivePlacement", "import_graphics.interactive_placement" );
  545. ret &= fromLegacyString( aCfg, "LastFile", "import_graphics.last_file" );
  546. ret &= fromLegacy<double>( aCfg, "LineWidth", "import_graphics.line_width" );
  547. ret &= fromLegacy<int>( aCfg, "LineWidthUnits", "import_graphics.line_width_units" );
  548. ret &= fromLegacy<int>( aCfg, "PositionUnits", "import_graphics.origin_units" );
  549. ret &= fromLegacy<double>( aCfg, "PositionX", "import_graphics.origin_x" );
  550. ret &= fromLegacy<double>( aCfg, "PositionY", "import_graphics.origin_y" );
  551. aCfg->SetPath( ".." );
  552. ret &= fromLegacy<int>( aCfg, "NetlistReportFilterMsg", "netlist.report_filter" );
  553. ret &= fromLegacy<bool>( aCfg, "NetlistUpdateFootprints", "netlist.update_footprints" );
  554. ret &= fromLegacy<bool>( aCfg, "NetlistDeleteShortingTracks", "netlist.delete_shorting_tracks" );
  555. ret &= fromLegacy<bool>( aCfg, "NetlistDeleteExtraFootprints", "netlist.delete_extra_footprints" );
  556. ret &= fromLegacy<int>( aCfg, "PlaceFileUnits", "place_file.units" );
  557. ret &= fromLegacy<int>( aCfg, "PlaceFileOpts", "place_file.file_options" );
  558. ret &= fromLegacy<int>( aCfg, "PlaceFileFormat", "place_file.file_format" );
  559. ret &= fromLegacy<bool>( aCfg, "PlaceFileIncludeBrdEdge", "place_file.include_board_edge" );
  560. ret &= fromLegacy<int>( aCfg, "PrintSinglePage", "plot.all_layers_on_one_page" );
  561. ret &= fromLegacy<int>( aCfg, "PrintPadsDrillOpt", "plot.pads_drill_mode" );
  562. ret &= fromLegacy<double>( aCfg, "PlotXFineScaleAdj", "plot.fine_scale_x" );
  563. ret &= fromLegacy<double>( aCfg, "PlotYFineScaleAdj", "plot.fine_scale_y" );
  564. ret &= fromLegacy<double>( aCfg, "PSPlotFineWidthAdj", "plot.ps_fine_width_adjust" );
  565. ret &= fromLegacy<bool>( aCfg, "CheckZonesBeforePlotting", "plot.check_zones_before_plotting" );
  566. ret &= fromLegacyString( aCfg, "FootprintTextShownColumns", "window.footprint_text_shown_columns" );
  567. ret &= fromLegacy<int>( aCfg, "FpWizardListWidth", "footprint_wizard_list.width" );
  568. ret &= fromLegacy<int>( aCfg, "FpWizardListHeight", "footprint_wizard_list.height" );
  569. migrateWindowConfig( aCfg, "ModViewFrame", "footprint_viewer" );
  570. ret &= fromLegacy<bool>( aCfg, "ModViewFrameAutoZoom", "footprint_viewer.auto_zoom" );
  571. ret &= fromLegacy<double>( aCfg, "ModViewFrameZoom", "footprint_viewer.zoom" );
  572. migrateWindowConfig( aCfg, "FootprintWizard", "footprint_wizard" );
  573. ret &= fromLegacyString( aCfg, "Fpwizard_auiPerspective", "footprint_wizard.perspective" );
  574. const std::string p = "pcbnew.InteractiveRouter.";
  575. Set( "tools.pns.meta", nlohmann::json( {
  576. { "filename", "pns" },
  577. { "version", 0 }
  578. } ) );
  579. ret &= fromLegacy<int>( aCfg, p + "Mode", "tools.pns.mode" );
  580. ret &= fromLegacy<int>( aCfg, p + "OptimizerEffort", "tools.pns.effort" );
  581. ret &= fromLegacy<bool>( aCfg, p + "RemoveLoops", "tools.pns.remove_loops" );
  582. ret &= fromLegacy<bool>( aCfg, p + "SmartPads", "tools.pns.smart_pads" );
  583. ret &= fromLegacy<bool>( aCfg, p + "ShoveVias", "tools.pns.shove_vias" );
  584. ret &= fromLegacy<bool>( aCfg, p + "StartDiagonal", "tools.pns.start_diagonal" );
  585. ret &= fromLegacy<int>( aCfg, p + "ShoveTimeLimit", "tools.pns.shove_time_limit" );
  586. ret &= fromLegacy<int>( aCfg, p + "ShoveIterationLimit", "tools.pns.shove_iteration_limit" );
  587. ret &= fromLegacy<int>( aCfg, p + "WalkaroundIterationLimit", "tools.pns.walkaround_iteration_limit" );
  588. ret &= fromLegacy<bool>( aCfg, p + "JumpOverObstacles", "tools.pns.jump_over_obstacles" );
  589. ret &= fromLegacy<bool>( aCfg, p + "SmoothDraggedSegments", "tools.pns.smooth_dragged_segments" );
  590. ret &= fromLegacy<bool>( aCfg, p + "CanViolateDRC", "tools.pns.can_violate_drc" );
  591. ret &= fromLegacy<bool>( aCfg, p + "SuggestFinish", "tools.pns.suggest_finish" );
  592. ret &= fromLegacy<bool>( aCfg, p + "FreeAngleMode", "tools.pns.free_angle_mode" );
  593. ret &= fromLegacy<bool>( aCfg, p + "InlineDragEnabled", "editing.track_drag_action" );
  594. // Initialize some new PNS settings to legacy behaviors if coming from legacy
  595. Set( "tools.pns.fix_all_segments", false );
  596. // Migrate color settings that were stored in the pcbnew config file
  597. COLOR_SETTINGS* cs = Pgm().GetSettingsManager().GetMigratedColorSettings();
  598. auto migrateLegacyColor =
  599. [&] ( const std::string& aKey, int aLayerId )
  600. {
  601. wxString str;
  602. if( aCfg->Read( aKey, &str ) )
  603. cs->SetColor( aLayerId, COLOR4D( str ) );
  604. };
  605. for( int i = 0; i < PCB_LAYER_ID_COUNT; ++i )
  606. {
  607. wxString layer = LSET::Name( PCB_LAYER_ID( i ) );
  608. migrateLegacyColor( "Color4DPCBLayer_" + layer.ToStdString(), PCB_LAYER_ID( i ) );
  609. }
  610. migrateLegacyColor( "Color4DAnchorEx", LAYER_ANCHOR );
  611. migrateLegacyColor( "Color4DAuxItems", LAYER_AUX_ITEMS );
  612. migrateLegacyColor( "Color4DGrid", LAYER_GRID );
  613. migrateLegacyColor( "Color4DNoNetPadMarker", LAYER_NO_CONNECTS );
  614. migrateLegacyColor( "Color4DNonPlatedEx", LAYER_NON_PLATEDHOLES );
  615. migrateLegacyColor( "Color4DPadThruHoleEx", LAYER_PADS_TH );
  616. migrateLegacyColor( "Color4DPCBBackground", LAYER_PCB_BACKGROUND );
  617. migrateLegacyColor( "Color4DPCBCursor", LAYER_CURSOR );
  618. migrateLegacyColor( "Color4DRatsEx", LAYER_RATSNEST );
  619. migrateLegacyColor( "Color4DTxtInvisEx", LAYER_MOD_TEXT_INVISIBLE );
  620. migrateLegacyColor( "Color4DViaBBlindEx", LAYER_VIA_BBLIND );
  621. migrateLegacyColor( "Color4DViaMicroEx", LAYER_VIA_MICROVIA );
  622. migrateLegacyColor( "Color4DViaThruEx", LAYER_VIA_THROUGH );
  623. migrateLegacyColor( "Color4DWorksheet", LAYER_DRAWINGSHEET );
  624. migrateLegacyColor( "Color4DGrid", LAYER_PAGE_LIMITS );
  625. Pgm().GetSettingsManager().SaveColorSettings( cs, "board" );
  626. Set( "appearance.color_theme", cs->GetFilename() );
  627. double x, y;
  628. if( aCfg->Read( f + "PcbUserGrid_X", &x ) && aCfg->Read( f + "PcbUserGrid_Y", &y ) )
  629. {
  630. EDA_UNITS u = static_cast<EDA_UNITS>( aCfg->ReadLong( f + "PcbUserGrid_Unit",
  631. static_cast<long>( EDA_UNITS::INCHES ) ) );
  632. // Convert to internal units
  633. x = From_User_Unit( u, x );
  634. y = From_User_Unit( u, y );
  635. Set( "window.grid.user_grid_x", StringFromValue( u, x ) );
  636. Set( "window.grid.user_grid_y", StringFromValue( u, y ) );
  637. }
  638. // Footprint editor settings were stored in pcbnew config file. Migrate them here.
  639. auto fpedit = Pgm().GetSettingsManager().GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( false );
  640. fpedit->MigrateFromLegacy( aCfg );
  641. fpedit->Load();
  642. // Same with 3D viewer
  643. auto viewer3d = Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>( false );
  644. viewer3d->MigrateFromLegacy( aCfg );
  645. viewer3d->Load();
  646. return ret;
  647. }
  648. //namespace py = pybind11;
  649. //
  650. //PYBIND11_MODULE( pcbnew, m )
  651. //{
  652. // py::class_<PCBNEW_SETTINGS>( m, "settings" )
  653. // .def_readwrite( "Use45DegreeGraphicSegments", &PCBNEW_SETTINGS::m_Use45DegreeGraphicSegments )
  654. // .def_readwrite( "FlipLeftRight", &PCBNEW_SETTINGS::m_FlipLeftRight )
  655. // .def_readwrite( "AddUnlockedPads", &PCBNEW_SETTINGS::m_AddUnlockedPads)
  656. // .def_readwrite( "UsePolarCoords", &PCBNEW_SETTINGS::m_PolarCoords)
  657. // .def_readwrite( "RotationAngle", &PCBNEW_SETTINGS::m_RotationAngle)
  658. // .def_readwrite( "ShowPageLimits", &PCBNEW_SETTINGS::m_ShowPageLimits)
  659. // ;
  660. //}