Files
kicad-source-mirror/pcbnew/footprint_editor_settings.cpp
Seth Hillbrand 81fbaacae2 Keep track of user layer mapping for footprints
Footprints in orgs have standard naming.  We need to allow designers to
keep their standard namings outside of boards where they are fixed.
This belongs in the preferences as a set-once for local standards
2025-01-28 12:22:39 -08:00

572 lines
26 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 Jon Evans <[email protected]>
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "footprint_editor_settings.h"
#include <common.h>
#include <layer_ids.h>
#include <lset.h>
#include <pgm_base.h>
#include <eda_text.h>
#include <pcb_dimension.h>
#include <settings/common_settings.h>
#include <settings/json_settings_internals.h>
#include <settings/parameters.h>
#include <settings/settings_manager.h>
#include <base_units.h>
#include <wx/config.h>
#include <wx/log.h>
///! Update the schema version whenever a migration is required
const int fpEditSchemaVersion = 4;
FOOTPRINT_EDITOR_SETTINGS::FOOTPRINT_EDITOR_SETTINGS() :
PCB_VIEWERS_SETTINGS_BASE( "fpedit", fpEditSchemaVersion ),
m_DesignSettings( nullptr, "fpedit.settings" ),
m_MagneticItems(),
m_Display(),
m_UserGrid(),
m_PolarCoords( false ),
m_DisplayInvertXAxis( false ),
m_DisplayInvertYAxis( false ),
m_RotationAngle( ANGLE_90 ),
m_Use45Limit( true ),
m_ArcEditMode( ARC_EDIT_MODE::KEEP_CENTER_ADJUST_ANGLE_RADIUS ),
m_LibWidth( 250 ),
m_LastExportPath(),
m_FootprintTextShownColumns()
{
m_MagneticItems.pads = MAGNETIC_OPTIONS::CAPTURE_ALWAYS;
m_MagneticItems.tracks = MAGNETIC_OPTIONS::NO_EFFECT;
m_MagneticItems.graphics = true;
m_MagneticItems.allLayers = false;
m_AuiPanels.appearance_panel_tab = 0;
m_AuiPanels.right_panel_width = -1;
m_AuiPanels.show_layer_manager = true;
m_params.emplace_back( new PARAM<int>( "window.lib_width",
&m_LibWidth, 250 ) );
m_params.emplace_back( new PARAM<bool>( "aui.show_layer_manager",
&m_AuiPanels.show_layer_manager, true ) );
m_params.emplace_back( new PARAM<int>( "aui.right_panel_width",
&m_AuiPanels.right_panel_width, -1 ) );
m_params.emplace_back( new PARAM<int>( "aui.appearance_panel_tab",
&m_AuiPanels.appearance_panel_tab, 0, 0, 2 ) );
m_params.emplace_back( new PARAM<int>( "aui.properties_panel_width",
&m_AuiPanels.properties_panel_width, -1 ) );
m_params.emplace_back( new PARAM<float>( "aui.properties_splitter_proportion",
&m_AuiPanels.properties_splitter, 0.5f ) );
m_params.emplace_back( new PARAM<bool>( "aui.show_properties",
&m_AuiPanels.show_properties, false ) );
m_params.emplace_back( new PARAM<int>( "library.sort_mode",
&m_LibrarySortMode, 0 ) );
m_params.emplace_back( new PARAM<wxString>( "system.last_import_export_path",
&m_LastExportPath, "" ) );
m_params.emplace_back( new PARAM<bool>( "pcb_display.graphics_fill",
&m_ViewersDisplay.m_DisplayGraphicsFill, true ) );
m_params.emplace_back( new PARAM<bool>( "pcb_display.text_fill",
&m_ViewersDisplay.m_DisplayTextFill, true ) );
m_params.emplace_back( new PARAM<bool>( "pcb_display.pad_fill",
&m_ViewersDisplay.m_DisplayPadFill, true ) );
m_params.emplace_back( new PARAM<bool>( "pcb_display.pad_numbers",
&m_ViewersDisplay.m_DisplayPadNumbers, true ) );
m_params.emplace_back( new PARAM<wxString>( "window.footprint_text_shown_columns",
&m_FootprintTextShownColumns, "0 1 2 3 4 5 7" ) );
m_params.emplace_back( new PARAM<int>( "editing.magnetic_pads",
reinterpret_cast<int*>( &m_MagneticItems.pads ),
static_cast<int>( MAGNETIC_OPTIONS::CAPTURE_ALWAYS ) ) );
m_params.emplace_back( new PARAM<bool>( "editing.magnetic_graphics",
&m_MagneticItems.graphics, true ) );
m_params.emplace_back( new PARAM<bool>( "editing.magnetic_all_layers",
&m_MagneticItems.allLayers, false ) );
m_params.emplace_back( new PARAM<bool>( "editing.polar_coords",
&m_PolarCoords, false ) );
m_params.emplace_back( new PARAM<bool>( "origin_invert_x_axis",
&m_DisplayInvertXAxis, false ) );
m_params.emplace_back( new PARAM<bool>( "origin_invert_y_axis",
&m_DisplayInvertYAxis, false ) );
m_params.emplace_back( new PARAM_LAMBDA<int>( "editing.rotation_angle",
[this] () -> int
{
return m_RotationAngle.AsTenthsOfADegree();
},
[this] ( int aVal )
{
if( aVal )
m_RotationAngle = EDA_ANGLE( aVal, TENTHS_OF_A_DEGREE_T );
},
900 ) );
m_params.emplace_back( new PARAM<bool>( "editing.fp_use_45_degree_limit",
&m_Use45Limit, false ) );
m_params.emplace_back( new PARAM_LAYER_PRESET( "pcb_display.layer_presets", &m_LayerPresets ) );
m_params.emplace_back( new PARAM<wxString>( "pcb_display.active_layer_preset",
&m_ActiveLayerPreset, "" ) );
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>(
"design_settings.default_footprint_text_items",
[&] () -> nlohmann::json
{
nlohmann::json js = nlohmann::json::array();
for( const TEXT_ITEM_INFO& item : m_DesignSettings.m_DefaultFPTextItems )
{
js.push_back( nlohmann::json( { item.m_Text.ToUTF8(),
item.m_Visible,
item.m_Layer } ) );
}
return js;
},
[&] ( const nlohmann::json& aObj )
{
m_DesignSettings.m_DefaultFPTextItems.clear();
if( !aObj.is_array() )
return;
for( const nlohmann::json& entry : aObj )
{
if( entry.empty() || !entry.is_array() )
continue;
TEXT_ITEM_INFO textInfo( wxT( "" ), true, F_SilkS );
textInfo.m_Text = entry.at(0).get<wxString>();
textInfo.m_Visible = entry.at(1).get<bool>();
textInfo.m_Layer = entry.at(2).get<int>();
m_DesignSettings.m_DefaultFPTextItems.push_back( std::move( textInfo ) );
}
},
nlohmann::json::array( {
{ "REF**", true, F_SilkS },
{ "", true, F_Fab },
{ "${REFERENCE}", true, F_Fab }
} ) ) );
m_params.emplace_back( new PARAM_MAP<wxString>( "design_settings.default_footprint_layer_names",
&m_DesignSettings.m_UserLayerNames, {} ) );
int minTextSize = pcbIUScale.mmToIU( TEXT_MIN_SIZE_MM );
int maxTextSize = pcbIUScale.mmToIU( TEXT_MAX_SIZE_MM );
int minStroke = 1;
int maxStroke = pcbIUScale.mmToIU( 100 );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_line_width",
&m_DesignSettings.m_LineThickness[ LAYER_CLASS_SILK ],
pcbIUScale.mmToIU( DEFAULT_SILK_LINE_WIDTH ), minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_size_h",
&m_DesignSettings.m_TextSize[ LAYER_CLASS_SILK ].x,
pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_size_v",
&m_DesignSettings.m_TextSize[ LAYER_CLASS_SILK ].y,
pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_thickness",
&m_DesignSettings.m_TextThickness[ LAYER_CLASS_SILK ],
pcbIUScale.mmToIU( DEFAULT_SILK_TEXT_WIDTH ), 1, maxTextSize, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM<bool>( "design_settings.silk_text_italic",
&m_DesignSettings.m_TextItalic[ LAYER_CLASS_SILK ], false ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_line_width",
&m_DesignSettings.m_LineThickness[ LAYER_CLASS_COPPER ],
pcbIUScale.mmToIU( DEFAULT_COPPER_LINE_WIDTH ), minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_size_h",
&m_DesignSettings.m_TextSize[ LAYER_CLASS_COPPER ].x,
pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_size_v",
&m_DesignSettings.m_TextSize[ LAYER_CLASS_COPPER ].y,
pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_thickness",
&m_DesignSettings.m_TextThickness[ LAYER_CLASS_COPPER ],
pcbIUScale.mmToIU( DEFAULT_COPPER_TEXT_WIDTH ), minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM<bool>( "design_settings.copper_text_italic",
&m_DesignSettings.m_TextItalic[ LAYER_CLASS_COPPER ], false ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.edge_line_width",
&m_DesignSettings.m_LineThickness[ LAYER_CLASS_EDGES ],
pcbIUScale.mmToIU( DEFAULT_EDGE_WIDTH ), minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.courtyard_line_width",
&m_DesignSettings.m_LineThickness[ LAYER_CLASS_COURTYARD ],
pcbIUScale.mmToIU( DEFAULT_COURTYARD_WIDTH ), minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_line_width",
&m_DesignSettings.m_LineThickness[ LAYER_CLASS_FAB ],
pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_size_h",
&m_DesignSettings.m_TextSize[ LAYER_CLASS_FAB ].x,
pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_size_v",
&m_DesignSettings.m_TextSize[ LAYER_CLASS_FAB ].y,
pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.fab_text_thickness",
&m_DesignSettings.m_TextThickness[ LAYER_CLASS_FAB ],
pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH ), 1, maxTextSize, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM<bool>( "design_settings.fab_text_italic",
&m_DesignSettings.m_TextItalic[ LAYER_CLASS_FAB ], false ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_line_width",
&m_DesignSettings.m_LineThickness[ LAYER_CLASS_OTHERS ],
pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), minStroke, maxStroke, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_size_h",
&m_DesignSettings.m_TextSize[ LAYER_CLASS_OTHERS ].x,
pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_size_v",
&m_DesignSettings.m_TextSize[ LAYER_CLASS_OTHERS ].y,
pcbIUScale.mmToIU( DEFAULT_TEXT_SIZE ), minTextSize, maxTextSize, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_thickness",
&m_DesignSettings.m_TextThickness[ LAYER_CLASS_OTHERS ],
pcbIUScale.mmToIU( DEFAULT_TEXT_WIDTH ), 1, maxTextSize, pcbIUScale.MM_PER_IU ) );
m_params.emplace_back( new PARAM<bool>( "design_settings.others_text_italic",
&m_DesignSettings.m_TextItalic[ LAYER_CLASS_OTHERS ], false ) );
// ---------------------------------------------------------------------------------------------
// Dimension settings
m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_MODE>( "design_settings.dimensions.units",
&m_DesignSettings.m_DimensionUnitsMode, DIM_UNITS_MODE::AUTOMATIC, DIM_UNITS_MODE::INCHES,
DIM_UNITS_MODE::AUTOMATIC ) );
m_params.emplace_back( new PARAM_ENUM<DIM_PRECISION>( "design_settings.dimensions.precision",
&m_DesignSettings.m_DimensionPrecision, DIM_PRECISION::X_XXXX, DIM_PRECISION::X, DIM_PRECISION::V_VVVVV ) );
m_params.emplace_back( new PARAM_ENUM<DIM_UNITS_FORMAT>( "design_settings.dimensions.units_format",
&m_DesignSettings.m_DimensionUnitsFormat, DIM_UNITS_FORMAT::NO_SUFFIX, DIM_UNITS_FORMAT::NO_SUFFIX,
DIM_UNITS_FORMAT::PAREN_SUFFIX ) );
m_params.emplace_back( new PARAM<bool>( "design_settings.dimensions.suppress_zeroes",
&m_DesignSettings.m_DimensionSuppressZeroes, true ) );
// NOTE: excluding DIM_TEXT_POSITION::MANUAL from the valid range here
m_params.emplace_back( new PARAM_ENUM<DIM_TEXT_POSITION>( "design_settings.dimensions.text_position",
&m_DesignSettings.m_DimensionTextPosition, DIM_TEXT_POSITION::OUTSIDE, DIM_TEXT_POSITION::OUTSIDE,
DIM_TEXT_POSITION::INLINE ) );
m_params.emplace_back( new PARAM<bool>( "design_settings.dimensions.keep_text_aligned",
&m_DesignSettings.m_DimensionKeepTextAligned, true ) );
m_params.emplace_back( new PARAM<int>( "design_settings.dimensions.arrow_length",
&m_DesignSettings.m_DimensionArrowLength,
pcbIUScale.MilsToIU( DEFAULT_DIMENSION_ARROW_LENGTH ) ) );
m_params.emplace_back( new PARAM<int>( "design_settings.dimensions.extension_offset",
&m_DesignSettings.m_DimensionExtensionOffset,
pcbIUScale.mmToIU( DEFAULT_DIMENSION_EXTENSION_OFFSET ) ) );
// ---------------------------------------------------------------------------------------------
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "editing.selection_filter",
[&]() -> nlohmann::json
{
nlohmann::json ret;
ret["lockedItems"] = m_SelectionFilter.lockedItems;
ret["footprints"] = m_SelectionFilter.footprints;
ret["text"] = m_SelectionFilter.text;
ret["tracks"] = m_SelectionFilter.tracks;
ret["vias"] = m_SelectionFilter.vias;
ret["pads"] = m_SelectionFilter.pads;
ret["graphics"] = m_SelectionFilter.graphics;
ret["zones"] = m_SelectionFilter.zones;
ret["keepouts"] = m_SelectionFilter.keepouts;
ret["dimensions"] = m_SelectionFilter.dimensions;
ret["otherItems"] = m_SelectionFilter.otherItems;
return ret;
},
[&]( const nlohmann::json& aVal )
{
if( aVal.empty() || !aVal.is_object() )
return;
SetIfPresent( aVal, "lockedItems", m_SelectionFilter.lockedItems );
SetIfPresent( aVal, "footprints", m_SelectionFilter.footprints );
SetIfPresent( aVal, "text", m_SelectionFilter.text );
SetIfPresent( aVal, "tracks", m_SelectionFilter.tracks );
SetIfPresent( aVal, "vias", m_SelectionFilter.vias );
SetIfPresent( aVal, "pads", m_SelectionFilter.pads );
SetIfPresent( aVal, "graphics", m_SelectionFilter.graphics );
SetIfPresent( aVal, "zones", m_SelectionFilter.zones );
SetIfPresent( aVal, "keepouts", m_SelectionFilter.keepouts );
SetIfPresent( aVal, "dimensions", m_SelectionFilter.dimensions );
SetIfPresent( aVal, "otherItems", m_SelectionFilter.otherItems );
},
{
{ "lockedItems", false },
{ "footprints", true },
{ "text", true },
{ "tracks", true },
{ "vias", true },
{ "pads", true },
{ "graphics", true },
{ "zones", true },
{ "keepouts", true },
{ "dimensions", true },
{ "otherItems", true }
} ) );
registerMigration( 0, 1, std::bind( &FOOTPRINT_EDITOR_SETTINGS::migrateSchema0to1, this ) );
registerMigration( 1, 2,
[&]() -> bool
{
// This is actually a migration for APP_SETTINGS_BASE::m_LibTree
return migrateLibTreeWidth();
} );
registerMigration( 2, 3, std::bind( &FOOTPRINT_EDITOR_SETTINGS::migrateSchema2To3, this ) );
registerMigration( 3, 4, std::bind( &FOOTPRINT_EDITOR_SETTINGS::migrateSchema3To4, this ) );
}
bool FOOTPRINT_EDITOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
{
bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
//
// NOTE: there's no value in line-wrapping these; it just makes the table unreadable.
//
ret &= fromLegacy<int>( aCfg, "ModeditLibWidth", "window.lib_width" );
ret &= fromLegacyString( aCfg, "import_last_path", "system.last_import_export_path" );
ret &= fromLegacyString( aCfg, "LibFootprintTextShownColumns", "window.footprint_text_shown_columns" );
ret &= fromLegacy<int>( aCfg, "FpEditorMagneticPads", "editing.magnetic_pads" );
ret &= fromLegacy<bool>( aCfg, "FpEditorDisplayPolarCoords", "editing.polar_coords" );
ret &= fromLegacy<int>( aCfg, "FpEditorUse45DegreeGraphicSegments", "editing.use_45_degree_graphic_segments" );
ret &= fromLegacy<bool>( aCfg, "FpEditorGraphicLinesDisplayMode", "pcb_display.graphic_items_fill" );
ret &= fromLegacy<bool>( aCfg, "FpEditorPadDisplayMode", "pcb_display.pad_fill" );
ret &= fromLegacy<bool>( aCfg, "FpEditorTextsDisplayMode", "pcb_display.footprint_text" );
ret &= fromLegacy<double>( aCfg, "FpEditorSilkLineWidth", "design_settings.silk_line_width" );
ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextSizeH", "design_settings.silk_text_size_h" );
ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextSizeV", "design_settings.silk_text_size_v" );
ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextThickness", "design_settings.silk_text_thickness" );
ret &= fromLegacy<bool>( aCfg, "FpEditorSilkTextItalic", "design_settings.silk_text_italic" );
ret &= fromLegacy<double>( aCfg, "FpEditorCopperLineWidth", "design_settings.copper_line_width" );
ret &= fromLegacy<double>( aCfg, "FpEditorCopperTextSizeH", "design_settings.copper_text_size_h" );
ret &= fromLegacy<double>( aCfg, "FpEditorCopperTextSizeV", "design_settings.copper_text_size_v" );
ret &= fromLegacy<double>( aCfg, "FpEditorCopperTextThickness", "design_settings.copper_text_thickness" );
ret &= fromLegacy<bool>( aCfg, "FpEditorCopperTextItalic", "design_settings.copper_text_italic" );
ret &= fromLegacy<double>( aCfg, "FpEditorEdgeCutLineWidth", "design_settings.edge_line_width" );
ret &= fromLegacy<double>( aCfg, "FpEditorCourtyardLineWidth", "design_settings.courtyard_line_width" );
ret &= fromLegacy<double>( aCfg, "FpEditorOthersLineWidth", "design_settings.others_line_width" );
ret &= fromLegacy<double>( aCfg, "FpEditorOthersTextSizeH", "design_settings.others_text_size_h" );
ret &= fromLegacy<double>( aCfg, "FpEditorOthersTextSizeV", "design_settings.others_text_size_v" );
ret &= fromLegacy<double>( aCfg, "FpEditorOthersTextThickness", "design_settings.others_text_thickness" );
ret &= fromLegacy<bool>( aCfg, "FpEditorOthersTextItalic", "design_settings.others_text_italic" );
nlohmann::json textItems = nlohmann::json::array( {
{ "REF**", true, F_SilkS },
{ "", true, F_Fab }
} );
Set( "design_settings.default_footprint_text_items", std::move( textItems ) );
ret &= fromLegacyString( aCfg, "FpEditorRefDefaultText", "design_settings.default_footprint_text_items.0.0" );
ret &= fromLegacy<bool>( aCfg, "FpEditorRefDefaultVisibility", "design_settings.default_footprint_text_items.0.1" );
ret &= fromLegacy<int>( aCfg, "FpEditorRefDefaultLayer", "design_settings.default_footprint_text_items.0.2" );
ret &= fromLegacyString( aCfg, "FpEditorValueDefaultText", "design_settings.default_footprint_text_items.1.0" );
ret &= fromLegacy<bool>( aCfg, "FpEditorValueDefaultVisibility", "design_settings.default_footprint_text_items.1.1" );
ret &= fromLegacy<int>( aCfg, "FpEditorValueDefaultLayer", "design_settings.default_footprint_text_items.1.2" );
std::string f = "ModEdit";
// Migrate color settings that were stored in the pcbnew config file
// We create a copy of the user scheme for the footprint editor context
SETTINGS_MANAGER& manager = Pgm().GetSettingsManager();
COLOR_SETTINGS* cs = manager.AddNewColorSettings( "user_footprints" );
cs->SetName( wxT( "User (Footprints)" ) );
manager.Save( cs );
auto migrateLegacyColor = [&] ( const std::string& aKey, int aLayerId )
{
wxString str;
if( aCfg->Read( aKey, &str ) )
cs->SetColor( aLayerId, COLOR4D( str ) );
};
for( int i = 0; i < PCB_LAYER_ID_COUNT; ++i )
{
wxString layer = LSET::Name( PCB_LAYER_ID( i ) );
migrateLegacyColor( f + "Color4DPCBLayer_" + layer.ToStdString(), PCB_LAYER_ID( i ) );
}
migrateLegacyColor( f + "Color4DAnchorEx", LAYER_ANCHOR );
migrateLegacyColor( f + "Color4DAuxItems", LAYER_AUX_ITEMS );
migrateLegacyColor( f + "Color4DGrid", LAYER_GRID );
migrateLegacyColor( f + "Color4DNonPlatedEx", LAYER_NON_PLATEDHOLES );
migrateLegacyColor( f + "Color4DPCBBackground", LAYER_PCB_BACKGROUND );
migrateLegacyColor( f + "Color4DPCBCursor", LAYER_CURSOR );
migrateLegacyColor( f + "Color4DRatsEx", LAYER_RATSNEST );
migrateLegacyColor( f + "Color4DViaBBlindEx", LAYER_VIA_BBLIND );
migrateLegacyColor( f + "Color4DViaMicroEx", LAYER_VIA_MICROVIA );
migrateLegacyColor( f + "Color4DViaThruEx", LAYER_VIA_THROUGH );
migrateLegacyColor( f + "Color4DWorksheet", LAYER_DRAWINGSHEET );
manager.SaveColorSettings( cs, "board" );
( *m_internals )[m_internals->PointerFromString( "appearance.color_theme" )] = "user_footprints";
double x = 0, y = 0;
f = "ModEditFrame";
if( aCfg->Read( f + "PcbUserGrid_X", &x ) && aCfg->Read( f + "PcbUserGrid_Y", &y ) )
{
EDA_UNITS u = static_cast<EDA_UNITS>( aCfg->ReadLong( f + "PcbUserGrid_Unit",
static_cast<long>( EDA_UNITS::INCHES ) ) );
// Convert to internal units
x = EDA_UNIT_UTILS::UI::FromUserUnit( pcbIUScale, u, x );
y = EDA_UNIT_UTILS::UI::FromUserUnit( pcbIUScale, u, y );
Set( "window.grid.user_grid_x", EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, u, x ) );
Set( "window.grid.user_grid_y", EDA_UNIT_UTILS::UI::StringFromValue( pcbIUScale, u, y ) );
}
return ret;
}
bool FOOTPRINT_EDITOR_SETTINGS::migrateSchema0to1()
{
/**
* Schema version 0 to 1:
*
* - Check to see if a footprints version of the currently selected theme exists.
* - If so, select it
*/
if( !m_manager )
{
wxLogTrace( traceSettings,
wxT( "Error: FOOTPRINT_EDITOR_SETTINGS migration cannot run unmanaged!" ) );
return false;
}
std::string theme_ptr( "appearance.color_theme" );
if( !Contains( theme_ptr ) )
return true;
wxString selected = At( theme_ptr ).get<wxString>();
wxString search = selected + wxT( "_footprints" );
for( COLOR_SETTINGS* settings : Pgm().GetSettingsManager().GetColorSettingsList() )
{
if( settings->GetFilename() == search )
{
wxLogTrace( traceSettings, wxT( "Updating footprint editor theme from %s to %s" ),
selected, search );
Set( theme_ptr, search );
return true;
}
}
return true;
}
/**
* Schema version 2: Bump for KiCad 9 layer numbering changes
* Migrate layer presets to use new enum values for copper layers
*/
bool FOOTPRINT_EDITOR_SETTINGS::migrateSchema2To3()
{
auto p( "/pcb_display/layer_presets"_json_pointer );
if( !m_internals->contains( p ) || !m_internals->at( p ).is_array() )
return true;
nlohmann::json& presets = m_internals->at( p );
for( nlohmann::json& entry : presets )
PARAM_LAYER_PRESET::MigrateToV9Layers( entry );
return true;
}
/**
* Schema version 4: move layer presets to use named render layers
*/
bool FOOTPRINT_EDITOR_SETTINGS::migrateSchema3To4()
{
auto p( "/pcb_display/layer_presets"_json_pointer );
if( !m_internals->contains( p ) || !m_internals->at( p ).is_array() )
return true;
nlohmann::json& presets = m_internals->at( p );
for( nlohmann::json& entry : presets )
PARAM_LAYER_PRESET::MigrateToNamedRenderLayers( entry );
return true;
}