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.

450 lines
21 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
  5. * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software: you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the
  9. * Free Software Foundation, either version 3 of the License, or (at your
  10. * option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <common.h>
  21. #include <footprint_editor_settings.h>
  22. #include <layer_ids.h>
  23. #include <pgm_base.h>
  24. #include <settings/common_settings.h>
  25. #include <settings/json_settings_internals.h>
  26. #include <settings/parameters.h>
  27. #include <settings/settings_manager.h>
  28. #include <wx/config.h>
  29. #include <base_units.h>
  30. #include <widgets/ui_common.h>
  31. #include <wx/log.h>
  32. #include <pcbnew.h>
  33. ///! Update the schema version whenever a migration is required
  34. const int fpEditSchemaVersion = 1;
  35. FOOTPRINT_EDITOR_SETTINGS::FOOTPRINT_EDITOR_SETTINGS() :
  36. APP_SETTINGS_BASE( "fpedit", fpEditSchemaVersion ),
  37. m_DesignSettings( nullptr, "fpedit.settings" ),
  38. m_MagneticItems(),
  39. m_Display(),
  40. m_UserGrid(),
  41. m_PolarCoords( false ),
  42. m_RotationAngle( ANGLE_90 ),
  43. m_Use45Limit( true ),
  44. m_LibWidth( 250 ),
  45. m_LastImportExportPath(),
  46. m_FootprintTextShownColumns()
  47. {
  48. m_MagneticItems.pads = MAGNETIC_OPTIONS::CAPTURE_ALWAYS;
  49. m_MagneticItems.tracks = MAGNETIC_OPTIONS::NO_EFFECT;
  50. m_MagneticItems.graphics = true;
  51. m_AuiPanels.appearance_panel_tab = 0;
  52. m_AuiPanels.right_panel_width = -1;
  53. m_AuiPanels.show_layer_manager = true;
  54. m_params.emplace_back( new PARAM<int>( "window.lib_width",
  55. &m_LibWidth, 250 ) );
  56. m_params.emplace_back( new PARAM<bool>( "aui.show_layer_manager",
  57. &m_AuiPanels.show_layer_manager, true ) );
  58. m_params.emplace_back( new PARAM<int>( "aui.right_panel_width",
  59. &m_AuiPanels.right_panel_width, -1 ) );
  60. m_params.emplace_back( new PARAM<int>( "aui.appearance_panel_tab",
  61. &m_AuiPanels.appearance_panel_tab, 0, 0, 2 ) );
  62. m_params.emplace_back( new PARAM<wxString>( "system.last_import_export_path",
  63. &m_LastImportExportPath, "" ) );
  64. m_params.emplace_back( new PARAM<wxString>( "window.footprint_text_shown_columns",
  65. &m_FootprintTextShownColumns, "0 1 2 3 4 5 6" ) );
  66. m_params.emplace_back( new PARAM<int>( "editing.magnetic_pads",
  67. reinterpret_cast<int*>( &m_MagneticItems.pads ),
  68. static_cast<int>( MAGNETIC_OPTIONS::CAPTURE_ALWAYS ) ) );
  69. m_params.emplace_back( new PARAM<bool>( "editing.magnetic_graphics",
  70. &m_MagneticItems.graphics, true ) );
  71. m_params.emplace_back( new PARAM<bool>( "editing.polar_coords",
  72. &m_PolarCoords, false ) );
  73. m_params.emplace_back( new PARAM_LAMBDA<int>( "editing.rotation_angle",
  74. [this] () -> int
  75. {
  76. return m_RotationAngle.AsTenthsOfADegree();
  77. },
  78. [this] ( int aVal )
  79. {
  80. if( aVal )
  81. m_RotationAngle = EDA_ANGLE( aVal, TENTHS_OF_A_DEGREE_T );
  82. },
  83. 900 ) );
  84. m_params.emplace_back( new PARAM<bool>( "editing.fp_use_45_degree_limit",
  85. &m_Use45Limit, false ) );
  86. m_params.emplace_back( new PARAM_LAYER_PRESET( "pcb_display.layer_presets", &m_LayerPresets ) );
  87. m_params.emplace_back( new PARAM<wxString>( "pcb_display.active_layer_preset",
  88. &m_ActiveLayerPreset, "" ) );
  89. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>(
  90. "design_settings.default_footprint_text_items",
  91. [&] () -> nlohmann::json
  92. {
  93. nlohmann::json js = nlohmann::json::array();
  94. for( const TEXT_ITEM_INFO& item : m_DesignSettings.m_DefaultFPTextItems )
  95. {
  96. js.push_back( nlohmann::json( { item.m_Text.ToUTF8(),
  97. item.m_Visible,
  98. item.m_Layer } ) );
  99. }
  100. return js;
  101. },
  102. [&] ( const nlohmann::json& aObj )
  103. {
  104. m_DesignSettings.m_DefaultFPTextItems.clear();
  105. if( !aObj.is_array() )
  106. return;
  107. for( const nlohmann::json& entry : aObj )
  108. {
  109. if( entry.empty() || !entry.is_array() )
  110. continue;
  111. TEXT_ITEM_INFO textInfo( wxT( "" ), true, F_SilkS );
  112. textInfo.m_Text = entry.at(0).get<wxString>();
  113. textInfo.m_Visible = entry.at(1).get<bool>();
  114. textInfo.m_Layer = entry.at(2).get<int>();
  115. m_DesignSettings.m_DefaultFPTextItems.push_back( std::move( textInfo ) );
  116. }
  117. },
  118. nlohmann::json::array( {
  119. { "REF**", true, F_SilkS },
  120. { "", true, F_Fab },
  121. { "${REFERENCE}", true, F_Fab }
  122. } ) ) );
  123. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_line_width",
  124. &m_DesignSettings.m_LineThickness[ LAYER_CLASS_SILK ],
  125. Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 100.0 ),
  126. MM_PER_IU ) );
  127. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_size_h",
  128. &m_DesignSettings.m_TextSize[ LAYER_CLASS_SILK ].x,
  129. Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
  130. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_size_v",
  131. &m_DesignSettings.m_TextSize[ LAYER_CLASS_SILK ].y,
  132. Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
  133. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_thickness",
  134. &m_DesignSettings.m_TextThickness[ LAYER_CLASS_SILK ],
  135. Millimeter2iu( DEFAULT_SILK_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
  136. m_params.emplace_back( new PARAM<bool>( "design_settings.silk_text_italic",
  137. &m_DesignSettings.m_TextItalic[ LAYER_CLASS_SILK ], false ) );
  138. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_line_width",
  139. &m_DesignSettings.m_LineThickness[ LAYER_CLASS_COPPER ],
  140. Millimeter2iu( DEFAULT_COPPER_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
  141. MM_PER_IU ) );
  142. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_size_h",
  143. &m_DesignSettings.m_TextSize[ LAYER_CLASS_COPPER ].x,
  144. Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE,
  145. MM_PER_IU ) );
  146. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_size_v",
  147. &m_DesignSettings.m_TextSize[ LAYER_CLASS_COPPER ].y,
  148. Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE,
  149. MM_PER_IU ) );
  150. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_thickness",
  151. &m_DesignSettings.m_TextThickness[ LAYER_CLASS_COPPER ],
  152. Millimeter2iu( DEFAULT_COPPER_TEXT_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
  153. MM_PER_IU ) );
  154. m_params.emplace_back( new PARAM<bool>( "design_settings.copper_text_italic",
  155. &m_DesignSettings.m_TextItalic[ LAYER_CLASS_COPPER ], false ) );
  156. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.edge_line_width",
  157. &m_DesignSettings.m_LineThickness[ LAYER_CLASS_EDGES ],
  158. Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
  159. MM_PER_IU ) );
  160. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.courtyard_line_width",
  161. &m_DesignSettings.m_LineThickness[ LAYER_CLASS_COURTYARD ],
  162. Millimeter2iu( DEFAULT_COURTYARD_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
  163. MM_PER_IU ) );
  164. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_line_width",
  165. &m_DesignSettings.m_LineThickness[ LAYER_CLASS_FAB ],
  166. Millimeter2iu( DEFAULT_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
  167. MM_PER_IU ) );
  168. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_size_h",
  169. &m_DesignSettings.m_TextSize[ LAYER_CLASS_FAB ].x,
  170. Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
  171. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_size_v",
  172. &m_DesignSettings.m_TextSize[ LAYER_CLASS_FAB ].y,
  173. Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
  174. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_thickness",
  175. &m_DesignSettings.m_TextThickness[ LAYER_CLASS_FAB ],
  176. Millimeter2iu( DEFAULT_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
  177. m_params.emplace_back( new PARAM<bool>( "design_settings.fab_text_italic",
  178. &m_DesignSettings.m_TextItalic[ LAYER_CLASS_FAB ], false ) );
  179. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_line_width",
  180. &m_DesignSettings.m_LineThickness[ LAYER_CLASS_OTHERS ],
  181. Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
  182. MM_PER_IU ) );
  183. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_size_h",
  184. &m_DesignSettings.m_TextSize[ LAYER_CLASS_OTHERS ].x,
  185. Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
  186. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_size_v",
  187. &m_DesignSettings.m_TextSize[ LAYER_CLASS_OTHERS ].y,
  188. Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
  189. m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_thickness",
  190. &m_DesignSettings.m_TextThickness[ LAYER_CLASS_OTHERS ],
  191. Millimeter2iu( DEFAULT_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
  192. m_params.emplace_back( new PARAM<bool>( "design_settings.others_text_italic",
  193. &m_DesignSettings.m_TextItalic[ LAYER_CLASS_OTHERS ], false ) );
  194. m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "editing.selection_filter",
  195. [&]() -> nlohmann::json
  196. {
  197. nlohmann::json ret;
  198. ret["lockedItems"] = m_SelectionFilter.lockedItems;
  199. ret["footprints"] = m_SelectionFilter.footprints;
  200. ret["text"] = m_SelectionFilter.text;
  201. ret["tracks"] = m_SelectionFilter.tracks;
  202. ret["vias"] = m_SelectionFilter.vias;
  203. ret["pads"] = m_SelectionFilter.pads;
  204. ret["graphics"] = m_SelectionFilter.graphics;
  205. ret["zones"] = m_SelectionFilter.zones;
  206. ret["keepouts"] = m_SelectionFilter.keepouts;
  207. ret["dimensions"] = m_SelectionFilter.dimensions;
  208. ret["otherItems"] = m_SelectionFilter.otherItems;
  209. return ret;
  210. },
  211. [&]( const nlohmann::json& aVal )
  212. {
  213. if( aVal.empty() || !aVal.is_object() )
  214. return;
  215. SetIfPresent( aVal, "lockedItems", m_SelectionFilter.lockedItems );
  216. SetIfPresent( aVal, "footprints", m_SelectionFilter.footprints );
  217. SetIfPresent( aVal, "text", m_SelectionFilter.text );
  218. SetIfPresent( aVal, "tracks", m_SelectionFilter.tracks );
  219. SetIfPresent( aVal, "vias", m_SelectionFilter.vias );
  220. SetIfPresent( aVal, "pads", m_SelectionFilter.pads );
  221. SetIfPresent( aVal, "graphics", m_SelectionFilter.graphics );
  222. SetIfPresent( aVal, "zones", m_SelectionFilter.zones );
  223. SetIfPresent( aVal, "keepouts", m_SelectionFilter.keepouts );
  224. SetIfPresent( aVal, "dimensions", m_SelectionFilter.dimensions );
  225. SetIfPresent( aVal, "otherItems", m_SelectionFilter.otherItems );
  226. },
  227. {
  228. { "lockedItems", true },
  229. { "footprints", true },
  230. { "text", true },
  231. { "tracks", true },
  232. { "vias", true },
  233. { "pads", true },
  234. { "graphics", true },
  235. { "zones", true },
  236. { "keepouts", true },
  237. { "dimensions", true },
  238. { "otherItems", true }
  239. } ) );
  240. registerMigration( 0, 1, std::bind( &FOOTPRINT_EDITOR_SETTINGS::migrateSchema0to1, this ) );
  241. }
  242. bool FOOTPRINT_EDITOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
  243. {
  244. bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
  245. //
  246. // NOTE: there's no value in line-wrapping these; it just makes the table unreadable.
  247. //
  248. ret &= fromLegacy<int>( aCfg, "ModeditLibWidth", "window.lib_width" );
  249. ret &= fromLegacyString( aCfg, "import_last_path", "system.last_import_export_path" );
  250. ret &= fromLegacyString( aCfg, "LibFootprintTextShownColumns", "window.footprint_text_shown_columns" );
  251. ret &= fromLegacy<int>( aCfg, "FpEditorMagneticPads", "editing.magnetic_pads" );
  252. ret &= fromLegacy<bool>( aCfg, "FpEditorDisplayPolarCoords", "editing.polar_coords" );
  253. ret &= fromLegacy<int>( aCfg, "FpEditorUse45DegreeGraphicSegments", "editing.use_45_degree_graphic_segments" );
  254. ret &= fromLegacy<bool>( aCfg, "FpEditorGraphicLinesDisplayMode", "pcb_display.graphic_items_fill" );
  255. ret &= fromLegacy<bool>( aCfg, "FpEditorPadDisplayMode", "pcb_display.pad_fill" );
  256. ret &= fromLegacy<bool>( aCfg, "FpEditorTextsDisplayMode", "pcb_display.footprint_text" );
  257. ret &= fromLegacy<double>( aCfg, "FpEditorSilkLineWidth", "design_settings.silk_line_width" );
  258. ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextSizeH", "design_settings.silk_text_size_h" );
  259. ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextSizeV", "design_settings.silk_text_size_v" );
  260. ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextThickness", "design_settings.silk_text_thickness" );
  261. ret &= fromLegacy<bool>( aCfg, "FpEditorSilkTextItalic", "design_settings.silk_text_italic" );
  262. ret &= fromLegacy<double>( aCfg, "FpEditorCopperLineWidth", "design_settings.copper_line_width" );
  263. ret &= fromLegacy<double>( aCfg, "FpEditorCopperTextSizeH", "design_settings.copper_text_size_h" );
  264. ret &= fromLegacy<double>( aCfg, "FpEditorCopperTextSizeV", "design_settings.copper_text_size_v" );
  265. ret &= fromLegacy<double>( aCfg, "FpEditorCopperTextThickness", "design_settings.copper_text_thickness" );
  266. ret &= fromLegacy<bool>( aCfg, "FpEditorCopperTextItalic", "design_settings.copper_text_italic" );
  267. ret &= fromLegacy<double>( aCfg, "FpEditorEdgeCutLineWidth", "design_settings.edge_line_width" );
  268. ret &= fromLegacy<double>( aCfg, "FpEditorCourtyardLineWidth", "design_settings.courtyard_line_width" );
  269. ret &= fromLegacy<double>( aCfg, "FpEditorOthersLineWidth", "design_settings.others_line_width" );
  270. ret &= fromLegacy<double>( aCfg, "FpEditorOthersTextSizeH", "design_settings.others_text_size_h" );
  271. ret &= fromLegacy<double>( aCfg, "FpEditorOthersTextSizeV", "design_settings.others_text_size_v" );
  272. ret &= fromLegacy<double>( aCfg, "FpEditorOthersTextThickness", "design_settings.others_text_thickness" );
  273. ret &= fromLegacy<bool>( aCfg, "FpEditorOthersTextItalic", "design_settings.others_text_italic" );
  274. nlohmann::json textItems = nlohmann::json::array( {
  275. { "REF**", true, F_SilkS },
  276. { "", true, F_Fab }
  277. } );
  278. Set( "design_settings.default_footprint_text_items", textItems );
  279. ret &= fromLegacyString( aCfg, "FpEditorRefDefaultText", "design_settings.default_footprint_text_items.0.0" );
  280. ret &= fromLegacy<bool>( aCfg, "FpEditorRefDefaultVisibility", "design_settings.default_footprint_text_items.0.1" );
  281. ret &= fromLegacy<int>( aCfg, "FpEditorRefDefaultLayer", "design_settings.default_footprint_text_items.0.2" );
  282. ret &= fromLegacyString( aCfg, "FpEditorValueDefaultText", "design_settings.default_footprint_text_items.1.0" );
  283. ret &= fromLegacy<bool>( aCfg, "FpEditorValueDefaultVisibility", "design_settings.default_footprint_text_items.1.1" );
  284. ret &= fromLegacy<int>( aCfg, "FpEditorValueDefaultLayer", "design_settings.default_footprint_text_items.1.2" );
  285. std::string f = "ModEdit";
  286. // Migrate color settings that were stored in the pcbnew config file
  287. // We create a copy of the user scheme for the footprint editor context
  288. SETTINGS_MANAGER& manager = Pgm().GetSettingsManager();
  289. COLOR_SETTINGS* cs = manager.AddNewColorSettings( "user_footprints" );
  290. cs->SetName( wxT( "User (Footprints)" ) );
  291. manager.Save( cs );
  292. auto migrateLegacyColor = [&] ( const std::string& aKey, int aLayerId )
  293. {
  294. wxString str;
  295. if( aCfg->Read( aKey, &str ) )
  296. cs->SetColor( aLayerId, COLOR4D( str ) );
  297. };
  298. for( int i = 0; i < PCB_LAYER_ID_COUNT; ++i )
  299. {
  300. wxString layer = LSET::Name( PCB_LAYER_ID( i ) );
  301. migrateLegacyColor( f + "Color4DPCBLayer_" + layer.ToStdString(), PCB_LAYER_ID( i ) );
  302. }
  303. migrateLegacyColor( f + "Color4DAnchorEx", LAYER_ANCHOR );
  304. migrateLegacyColor( f + "Color4DAuxItems", LAYER_AUX_ITEMS );
  305. migrateLegacyColor( f + "Color4DGrid", LAYER_GRID );
  306. migrateLegacyColor( f + "Color4DNoNetPadMarker", LAYER_NO_CONNECTS );
  307. migrateLegacyColor( f + "Color4DNonPlatedEx", LAYER_NON_PLATEDHOLES );
  308. migrateLegacyColor( f + "Color4DPadThruHoleEx", LAYER_PADS_TH );
  309. migrateLegacyColor( f + "Color4DPCBBackground", LAYER_PCB_BACKGROUND );
  310. migrateLegacyColor( f + "Color4DPCBCursor", LAYER_CURSOR );
  311. migrateLegacyColor( f + "Color4DRatsEx", LAYER_RATSNEST );
  312. migrateLegacyColor( f + "Color4DTxtInvisEx", LAYER_MOD_TEXT_INVISIBLE );
  313. migrateLegacyColor( f + "Color4DViaBBlindEx", LAYER_VIA_BBLIND );
  314. migrateLegacyColor( f + "Color4DViaMicroEx", LAYER_VIA_MICROVIA );
  315. migrateLegacyColor( f + "Color4DViaThruEx", LAYER_VIA_THROUGH );
  316. migrateLegacyColor( f + "Color4DWorksheet", LAYER_DRAWINGSHEET );
  317. manager.SaveColorSettings( cs, "board" );
  318. ( *m_internals )[m_internals->PointerFromString( "appearance.color_theme" )] = "user_footprints";
  319. double x, y;
  320. f = "ModEditFrame";
  321. if( aCfg->Read( f + "PcbUserGrid_X", &x ) && aCfg->Read( f + "PcbUserGrid_Y", &y ) )
  322. {
  323. EDA_UNITS u = static_cast<EDA_UNITS>( aCfg->ReadLong( f + "PcbUserGrid_Unit",
  324. static_cast<long>( EDA_UNITS::INCHES ) ) );
  325. // Convert to internal units
  326. x = From_User_Unit( u, x );
  327. y = From_User_Unit( u, y );
  328. Set( "window.grid.user_grid_x", StringFromValue( u, x ) );
  329. Set( "window.grid.user_grid_y", StringFromValue( u, y ) );
  330. }
  331. return ret;
  332. }
  333. bool FOOTPRINT_EDITOR_SETTINGS::migrateSchema0to1()
  334. {
  335. /**
  336. * Schema version 0 to 1:
  337. *
  338. * - Check to see if a footprints version of the currently selected theme exists.
  339. * - If so, select it
  340. */
  341. if( !m_manager )
  342. {
  343. wxLogTrace( traceSettings,
  344. "Error: FOOTPRINT_EDITOR_SETTINGS migration cannot run unmanaged!" );
  345. return false;
  346. }
  347. std::string theme_ptr( "appearance.color_theme" );
  348. if( !Count( theme_ptr ) )
  349. return true;
  350. wxString selected = At( theme_ptr ).get<wxString>();
  351. wxString search = selected + wxT( "_footprints" );
  352. for( COLOR_SETTINGS* settings : Pgm().GetSettingsManager().GetColorSettingsList() )
  353. {
  354. if( settings->GetFilename() == search )
  355. {
  356. wxLogTrace( traceSettings, "Updating footprint editor theme from %s to %s",
  357. selected, search );
  358. Set( theme_ptr, search );
  359. return true;
  360. }
  361. }
  362. return true;
  363. }