/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2020 CERN * @author Jon Evans * * 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 . */ #include #include #include const int projectLocalSettingsVersion = 2; PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxString& aFilename ) : JSON_SETTINGS( aFilename, SETTINGS_LOC::PROJECT, projectLocalSettingsVersion, /* aCreateIfMissing = */ true, /* aCreateIfDefault = */ false, /* aWriteFile = */ true ), m_project( aProject ), m_SelectionFilter() { m_params.emplace_back( new PARAM_LAMBDA( "board.visible_layers", [&]() -> std::string { return m_VisibleLayers.FmtHex(); }, [&]( const std::string& aString ) { m_VisibleLayers.ParseHex( aString.c_str(), aString.size() ); }, LSET::AllLayersMask().FmtHex() ) ); m_params.emplace_back( new PARAM_LAMBDA( "board.visible_items", [&]() -> nlohmann::json { nlohmann::json ret = nlohmann::json::array(); for( size_t i = 0; i < m_VisibleItems.size(); i++ ) if( m_VisibleItems.test( i ) ) ret.push_back( i ); return ret; }, [&]( const nlohmann::json& aVal ) { if( !aVal.is_array() || aVal.empty() ) { m_VisibleItems = GAL_SET::DefaultVisible(); return; } m_VisibleItems.reset(); for( const nlohmann::json& entry : aVal ) { try { int i = entry.get(); m_VisibleItems.set( i ); } catch( ... ) { // Non-integer or out of range entry in the array; ignore } } }, {} ) ); m_params.emplace_back( new PARAM_LAMBDA( "board.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; auto setIfPresent = [&aVal]( const std::string& aKey, bool& aTarget ) { if( aVal.contains( aKey ) && aVal.at( aKey ).is_boolean() ) aTarget = aVal.at( aKey ).get(); }; setIfPresent( "lockedItems", m_SelectionFilter.lockedItems ); setIfPresent( "footprints", m_SelectionFilter.footprints ); setIfPresent( "text", m_SelectionFilter.text ); setIfPresent( "tracks", m_SelectionFilter.tracks ); setIfPresent( "vias", m_SelectionFilter.vias ); setIfPresent( "pads", m_SelectionFilter.pads ); setIfPresent( "graphics", m_SelectionFilter.graphics ); setIfPresent( "zones", m_SelectionFilter.zones ); setIfPresent( "keepouts", m_SelectionFilter.keepouts ); setIfPresent( "dimensions", m_SelectionFilter.dimensions ); setIfPresent( "otherItems", m_SelectionFilter.otherItems ); }, { { "lockedItems", true }, { "footprints", true }, { "text", true }, { "tracks", true }, { "vias", true }, { "pads", true }, { "graphics", true }, { "zones", true }, { "keepouts", true }, { "dimensions", true }, { "otherItems", true } } ) ); m_params.emplace_back( new PARAM_ENUM( "board.active_layer", &m_ActiveLayer, F_Cu, PCBNEW_LAYER_ID_START, F_Fab ) ); m_params.emplace_back( new PARAM( "board.active_layer_preset", &m_ActiveLayerPreset, "" ) ); m_params.emplace_back( new PARAM_ENUM( "board.high_contrast_mode", &m_ContrastModeDisplay, HIGH_CONTRAST_MODE::NORMAL, HIGH_CONTRAST_MODE::NORMAL, HIGH_CONTRAST_MODE::HIDDEN ) ); m_params.emplace_back( new PARAM( "board.opacity.tracks", &m_TrackOpacity, 1.0 ) ); m_params.emplace_back( new PARAM( "board.opacity.vias", &m_ViaOpacity, 1.0 ) ); m_params.emplace_back( new PARAM( "board.opacity.pads", &m_PadOpacity, 1.0 ) ); m_params.emplace_back( new PARAM( "board.opacity.zones", &m_ZoneOpacity, 1.0 ) ); m_params.emplace_back( new PARAM_LIST( "board.hidden_nets", &m_HiddenNets, {} ) ); m_params.emplace_back( new PARAM_ENUM( "board.net_color_mode", &m_NetColorMode, NET_COLOR_MODE::RATSNEST, NET_COLOR_MODE::OFF, NET_COLOR_MODE::ALL ) ); // TODO: move the rest of PCB_DISPLAY_OPTIONS that are project-specific in here #if 0 m_params.emplace_back( new PARAM_ENUM( "board.zone_display_mode", &m_ZoneDisplayMode, ZONE_DISPLAY_MODE::SHOW_FILLED, ZONE_DISPLAY_MODE::SHOW_OUTLINED, ZONE_DISPLAY_MODE::SHOW_FILLED ) ); #endif } bool PROJECT_LOCAL_SETTINGS::MigrateFromLegacy( wxConfigBase* aLegacyConfig ) { /** * The normal legacy migration code won't be used for this because the only legacy * information stored here was stored in board files, so we do that migration when loading * the board. */ return true; } bool PROJECT_LOCAL_SETTINGS::SaveToFile( const wxString& aDirectory, bool aForce ) { wxASSERT( m_project ); ( *this )[PointerFromString( "meta.filename" )] = m_project->GetProjectName() + "." + ProjectLocalSettingsFileExtension; return JSON_SETTINGS::SaveToFile( aDirectory, aForce ); } bool PROJECT_LOCAL_SETTINGS::Migrate() { bool ret = true; int filever = at( PointerFromString( "meta.version" ) ).get(); if( filever == 1 ) { ret &= migrateSchema1to2(); if( ret ) ( *this )[PointerFromString( "meta.version" )] = 2; } return ret; } bool PROJECT_LOCAL_SETTINGS::migrateSchema1to2() { /** * Schema version 1 to 2: * LAYER_PADS and LAYER_ZONES added to visibility controls */ nlohmann::json::json_pointer ptr( "/board/visible_items"_json_pointer ); if( contains( ptr ) ) { if( ( *this )[ptr].is_array() ) { ( *this )[ptr].push_back( LAYER_PADS ); ( *this )[ptr].push_back( LAYER_ZONES ); } else { at( "board" ).erase( "visible_items" ); } } return true; }