kicad/common/project/project_local_settings.cpp

232 lines
8.3 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 CERN
* @author Jon Evans <jon@craftyjon.com>
*
* 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 <project.h>
#include <project/project_local_settings.h>
#include <settings/parameters.h>
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<std::string>( "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<nlohmann::json>( "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<int>();
m_VisibleItems.set( i );
}
catch( ... )
{
// Non-integer or out of range entry in the array; ignore
}
}
},
{} ) );
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "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<bool>();
};
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<PCB_LAYER_ID>(
"board.active_layer", &m_ActiveLayer, F_Cu, PCBNEW_LAYER_ID_START, F_Fab ) );
m_params.emplace_back( new PARAM<wxString>( "board.active_layer_preset",
&m_ActiveLayerPreset, "" ) );
m_params.emplace_back( new PARAM_ENUM<HIGH_CONTRAST_MODE>( "board.high_contrast_mode",
&m_ContrastModeDisplay, HIGH_CONTRAST_MODE::NORMAL, HIGH_CONTRAST_MODE::NORMAL,
HIGH_CONTRAST_MODE::HIDDEN ) );
m_params.emplace_back( new PARAM<double>( "board.opacity.tracks", &m_TrackOpacity, 1.0 ) );
m_params.emplace_back( new PARAM<double>( "board.opacity.vias", &m_ViaOpacity, 1.0 ) );
m_params.emplace_back( new PARAM<double>( "board.opacity.pads", &m_PadOpacity, 1.0 ) );
m_params.emplace_back( new PARAM<double>( "board.opacity.zones", &m_ZoneOpacity, 1.0 ) );
m_params.emplace_back( new PARAM_LIST<wxString>( "board.hidden_nets", &m_HiddenNets, {} ) );
m_params.emplace_back( new PARAM_ENUM<NET_COLOR_MODE>( "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<ZONE_DISPLAY_MODE>( "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<int>();
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;
}