Migrate PcbNew project settings to new framework

Various architecture upgrades to support this.
Creating a BOARD now requires a valid PROJECT, which caused
some (mostly transparent) changes to the Python API internals.

ADDED: Project local settings file
CHANGED: Board design settings are no longer stored in PCB file
CHANGED: Net classes are no longer stored in PCB file
CHANGED: Importing board settings now reads boards, not just projects

Fixes https://gitlab.com/kicad/code/kicad/-/issues/2578
Fixes https://gitlab.com/kicad/code/kicad/-/issues/4070
This commit is contained in:
Jon Evans 2020-05-31 17:42:04 -04:00
parent 0e2f9cb1bd
commit c0aa6965de
87 changed files with 2415 additions and 1933 deletions

View File

@ -188,8 +188,7 @@ bool BOARD_ADAPTER::Is3DLayerEnabled( PCB_LAYER_ID aLayer ) const
case B_Cu:
case F_Cu:
return m_board->GetDesignSettings().IsLayerVisible( aLayer ) ||
GetFlag( FL_USE_REALISTIC_MODE );
return m_board->IsLayerVisible( aLayer ) || GetFlag( FL_USE_REALISTIC_MODE );
break;
default:
@ -201,7 +200,7 @@ bool BOARD_ADAPTER::Is3DLayerEnabled( PCB_LAYER_ID aLayer ) const
return false;
}
return m_board->GetDesignSettings().IsLayerVisible( aLayer );
return m_board->IsLayerVisible( aLayer );
}
// The layer has a flag, return the flag

View File

@ -317,8 +317,10 @@ set( COMMON_SRCS
lib_tree_model.cpp
lib_tree_model_adapter.cpp
lockfile.cpp
lset.cpp
marker_base.cpp
msgpanel.cpp
netclass.cpp
observable.cpp
prependpath.cpp
printout.cpp
@ -398,9 +400,12 @@ set( COMMON_SRCS
settings/common_settings.cpp
settings/json_settings.cpp
settings/nested_settings.cpp
settings/project_file.cpp
settings/settings_manager.cpp
project/net_settings.cpp
project/project_file.cpp
project/project_local_settings.cpp
libeval/numeric_evaluator.cpp
)
@ -438,7 +443,6 @@ set( PCB_COMMON_SRCS
eda_text.cpp
fp_lib_table.cpp
hash_eda.cpp
lset.cpp
origin_viewitem.cpp
page_info.cpp
${CMAKE_SOURCE_DIR}/pcbnew/pcb_base_frame.cpp
@ -453,7 +457,6 @@ set( PCB_COMMON_SRCS
${CMAKE_SOURCE_DIR}/pcbnew/class_edge_mod.cpp
${CMAKE_SOURCE_DIR}/pcbnew/class_marker_pcb.cpp
${CMAKE_SOURCE_DIR}/pcbnew/class_module.cpp
${CMAKE_SOURCE_DIR}/pcbnew/netclass.cpp
${CMAKE_SOURCE_DIR}/pcbnew/netinfo_item.cpp
${CMAKE_SOURCE_DIR}/pcbnew/netinfo_list.cpp
${CMAKE_SOURCE_DIR}/pcbnew/class_pad.cpp

View File

@ -24,6 +24,7 @@
#include <kiface_i.h>
#include <config_params.h>
#include <lib_tree_model_adapter.h>
#include <project/project_file.h>
#include <settings/app_settings.h>
#include <wx/tokenzr.h>
#include <wx/wupdlock.h>
@ -73,7 +74,7 @@ unsigned int LIB_TREE_MODEL_ADAPTER::IntoArray( LIB_TREE_NODE const& aNode,
}
LIB_TREE_MODEL_ADAPTER::LIB_TREE_MODEL_ADAPTER( EDA_BASE_FRAME* aParent ) :
LIB_TREE_MODEL_ADAPTER::LIB_TREE_MODEL_ADAPTER( EDA_BASE_FRAME* aParent, wxString aPinnedKey ) :
m_parent( aParent ),
m_filter( CMP_FILTER_NONE ),
m_show_units( true ),
@ -81,7 +82,9 @@ LIB_TREE_MODEL_ADAPTER::LIB_TREE_MODEL_ADAPTER( EDA_BASE_FRAME* aParent ) :
m_freeze( 0 ),
m_col_part( nullptr ),
m_col_desc( nullptr ),
m_widget( nullptr )
m_widget( nullptr ),
m_pinnedLibs(),
m_pinnedKey( aPinnedKey )
{
// Default column widths
m_colWidths[PART_COL] = 360;
@ -90,12 +93,15 @@ LIB_TREE_MODEL_ADAPTER::LIB_TREE_MODEL_ADAPTER( EDA_BASE_FRAME* aParent ) :
auto cfg = Kiface().KifaceSettings();
m_colWidths[PART_COL] = cfg->m_LibTree.column_width;
// TODO(JE) PROJECT
#if 0
// Read the pinned entries from the project config
m_parent->Kiway().Prj().ConfigLoad( Kiface().KifaceSearch(), m_parent->GetName(),
GetProjectFileParameters() );
#endif
PROJECT_FILE& project = m_parent->Kiway().Prj().GetProjectFile();
std::vector<wxString>& entries = ( m_pinnedKey == "pinned_symbol_libs" ) ?
project.m_PinnedSymbolLibs :
project.m_PinnedFootprintLibs;
for( const wxString& entry : entries )
m_pinnedLibs.push_back( entry );
}
@ -117,32 +123,27 @@ void LIB_TREE_MODEL_ADAPTER::SaveColWidths()
}
std::vector<PARAM_CFG*>& LIB_TREE_MODEL_ADAPTER::GetProjectFileParameters()
{
if( !m_projectFileParams.empty() )
return m_projectFileParams;
m_projectFileParams.push_back( new PARAM_CFG_LIBNAME_LIST( PINNED_ITEMS_KEY, &m_pinnedLibs ) );
return m_projectFileParams;
}
void LIB_TREE_MODEL_ADAPTER::SavePinnedItems()
{
PROJECT_FILE& project = m_parent->Kiway().Prj().GetProjectFile();
std::vector<wxString>& entries = ( m_pinnedKey == "pinned_symbol_libs" ) ?
project.m_PinnedSymbolLibs :
project.m_PinnedFootprintLibs;
entries.clear();
m_pinnedLibs.clear();
for( auto& child: m_tree.m_Children )
{
if( child->m_Pinned )
{
m_pinnedLibs.push_back( child->m_LibId.GetLibNickname() );
entries.push_back( child->m_LibId.GetLibNickname() );
}
}
// TODO(JE) PROJECT
#if 0
m_parent->Kiway().Prj().ConfigSave( Kiface().KifaceSearch(), m_parent->GetName(),
GetProjectFileParameters() );
#endif
}

View File

@ -136,8 +136,6 @@ public:
void SaveColWidths();
void SavePinnedItems();
std::vector<PARAM_CFG*>& GetProjectFileParameters();
/**
* Set the component filter type. Must be set before adding libraries
*
@ -282,7 +280,12 @@ protected:
LIB_TREE_NODE_ROOT m_tree;
LIB_TREE_MODEL_ADAPTER( EDA_BASE_FRAME* aParent );
/**
* Creates the adapter
* @param aParent is the parent frame
* @param aPinnedKey is the key to load the pinned libraries list from the project file
*/
LIB_TREE_MODEL_ADAPTER( EDA_BASE_FRAME* aParent, wxString aPinnedKey );
LIB_TREE_NODE_LIB& DoAddLibraryNode( wxString const& aNodeName, wxString const& aDesc );
@ -368,6 +371,7 @@ private:
int m_colWidths[NUM_COLS];
wxArrayString m_pinnedLibs;
wxString m_pinnedKey;
/**
* Find any results worth highlighting and expand them, according to given criteria

View File

@ -24,15 +24,16 @@
*/
#include <fctsys.h>
#include <common.h>
#include <kicad_string.h>
#include <pcbnew.h>
#include <richio.h>
#include <macros.h>
#include <class_board.h>
#include <netclass.h>
#ifndef PCBNEW
#define PCBNEW // needed to define the right value of Millimeter2iu(x)
#endif
#include <base_units.h>
// This will get mapped to "kicad_default" in the specctra_export.
const char NETCLASS::Default[] = "Default";
@ -152,84 +153,6 @@ NETCLASSPTR NETCLASSES::Find( const wxString& aName ) const
}
void BOARD::SynchronizeNetsAndNetClasses()
{
NETCLASSES& netClasses = m_designSettings.m_NetClasses;
NETCLASSPTR defaultNetClass = netClasses.GetDefault();
// set all NETs to the default NETCLASS, then later override some
// as we go through the NETCLASSes.
for( NETINFO_LIST::iterator net( m_NetInfo.begin() ), netEnd( m_NetInfo.end() );
net != netEnd; ++net )
{
net->SetClass( defaultNetClass );
}
// Add netclass name and pointer to nets. If a net is in more than one netclass,
// set the net's name and pointer to only the first netclass. Subsequent
// and therefore bogus netclass memberships will be deleted in logic below this loop.
for( NETCLASSES::iterator clazz = netClasses.begin(); clazz != netClasses.end(); ++clazz )
{
NETCLASSPTR netclass = clazz->second;
for( NETCLASS::const_iterator member = netclass->begin(); member != netclass->end(); ++member )
{
const wxString& netname = *member;
// although this overall function seems to be adequately fast,
// FindNet( wxString ) uses now a fast binary search and is fast
// event for large net lists
NETINFO_ITEM* net = FindNet( netname );
if( net && net->GetClassName() == NETCLASS::Default )
{
net->SetClass( netclass );
}
}
}
// Finally, make sure that every NET is in a NETCLASS, even if that
// means the Default NETCLASS. And make sure that all NETCLASSes do not
// contain netnames that do not exist, by deleting all netnames from
// every netclass and re-adding them.
for( NETCLASSES::iterator clazz = netClasses.begin(); clazz != netClasses.end(); ++clazz )
{
NETCLASSPTR netclass = clazz->second;
netclass->Clear();
}
defaultNetClass->Clear();
for( NETINFO_LIST::iterator net( m_NetInfo.begin() ), netEnd( m_NetInfo.end() );
net != netEnd; ++net )
{
const wxString& classname = net->GetClassName();
// because of the std:map<> this should be fast, and because of
// prior logic, netclass should not be NULL.
NETCLASSPTR netclass = netClasses.Find( classname );
wxASSERT( netclass );
netclass->Add( net->GetNetname() );
}
// Set initial values for custom track width & via size to match the default netclass settings
m_designSettings.UseCustomTrackViaSize( false );
m_designSettings.SetCustomTrackWidth( defaultNetClass->GetTrackWidth() );
m_designSettings.SetCustomViaSize( defaultNetClass->GetViaDiameter() );
m_designSettings.SetCustomViaDrill( defaultNetClass->GetViaDrill() );
m_designSettings.SetCustomDiffPairWidth( defaultNetClass->GetDiffPairWidth() );
m_designSettings.SetCustomDiffPairGap( defaultNetClass->GetDiffPairGap() );
m_designSettings.SetCustomDiffPairViaGap( defaultNetClass->GetDiffPairViaGap() );
InvokeListeners( &BOARD_LISTENER::OnBoardNetSettingsChanged, *this );
}
#if defined(DEBUG)
void NETCLASS::Show( int nestLevel, std::ostream& os ) const
@ -250,38 +173,3 @@ void NETCLASS::Show( int nestLevel, std::ostream& os ) const
}
#endif
void NETCLASS::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
{
aFormatter->Print( aNestLevel, "(net_class %s %s\n",
aFormatter->Quotew( GetName() ).c_str(),
aFormatter->Quotew( GetDescription() ).c_str() );
aFormatter->Print( aNestLevel+1, "(clearance %s)\n", FormatInternalUnits( GetClearance() ).c_str() );
aFormatter->Print( aNestLevel+1, "(trace_width %s)\n", FormatInternalUnits( GetTrackWidth() ).c_str() );
aFormatter->Print( aNestLevel+1, "(via_dia %s)\n", FormatInternalUnits( GetViaDiameter() ).c_str() );
aFormatter->Print( aNestLevel+1, "(via_drill %s)\n", FormatInternalUnits( GetViaDrill() ).c_str() );
aFormatter->Print( aNestLevel+1, "(uvia_dia %s)\n", FormatInternalUnits( GetuViaDiameter() ).c_str() );
aFormatter->Print( aNestLevel+1, "(uvia_drill %s)\n", FormatInternalUnits( GetuViaDrill() ).c_str() );
// Save the diff_pair_gap and diff_pair_width values only if not the default, to avoid unnecessary
// incompatibility with previous Pcbnew versions.
if( ( DEFAULT_DIFF_PAIR_WIDTH != GetDiffPairWidth() ) ||
( DEFAULT_DIFF_PAIR_GAP != GetDiffPairGap() ) )
{
aFormatter->Print( aNestLevel+1, "(diff_pair_width %s)\n",
FormatInternalUnits( GetDiffPairWidth() ).c_str() );
aFormatter->Print( aNestLevel+1, "(diff_pair_gap %s)\n",
FormatInternalUnits( GetDiffPairGap() ).c_str() );
// 6.0 TODO: figure out what to do with DiffPairViaGap...
}
for( NETCLASS::const_iterator it = begin(); it != end(); ++it )
aFormatter->Print( aNestLevel+1, "(add_net %s)\n", aFormatter->Quotew( *it ).c_str() );
aFormatter->Print( aNestLevel, ")\n\n" );
}

View File

@ -23,20 +23,20 @@
#include <wx/stdpaths.h>
#include <common.h> // NAMELESS_PROJECT
#include <config_params.h>
#include <confirm.h>
#include <fctsys.h>
#include <fp_lib_table.h>
#include <kicad_string.h>
#include <kiface_ids.h>
#include <kiway.h>
#include <macros.h>
#include <pgm_base.h>
#include <project.h>
#include <common.h> // NAMELESS_PROJECT
#include <confirm.h>
#include <kicad_string.h>
#include <config_params.h>
#include <wildcards_and_files_ext.h>
#include <fp_lib_table.h>
#include <kiway.h>
#include <kiface_ids.h>
#include <project/project_file.h>
#include <trace_helpers.h>
#include <settings/project_file.h>
#include <wildcards_and_files_ext.h>
PROJECT::PROJECT() :

View File

@ -0,0 +1,142 @@
/*
* 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/net_settings.h>
#include <settings/parameters.h>
// Netclasses were originally only stored in board files. The IU context is PCBNEW.
#ifndef PCBNEW
#define PCBNEW
#endif
#include <base_units.h>
const int netSettingsSchemaVersion = 0;
NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
NESTED_SETTINGS( "net_settings", netSettingsSchemaVersion, aParent, aPath ),
m_NetClasses()
{
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "classes",
[&]() -> nlohmann::json
{
nlohmann::json ret = nlohmann::json::array();
NETCLASSPTR netclass = m_NetClasses.GetDefault();
NETCLASSES::const_iterator nc = m_NetClasses.begin();
for( unsigned int idx = 0; idx <= m_NetClasses.GetCount(); idx++ )
{
if( idx > 0 )
{
netclass = nc->second;
++nc;
}
nlohmann::json netJson = {
{ "name", netclass->GetName().ToUTF8() },
{ "clearance", Iu2Millimeter( netclass->GetClearance() ) },
{ "track_width", Iu2Millimeter( netclass->GetTrackWidth() ) },
{ "via_diameter", Iu2Millimeter( netclass->GetViaDiameter() ) },
{ "via_drill", Iu2Millimeter( netclass->GetViaDrill() ) },
{ "microvia_diameter", Iu2Millimeter( netclass->GetuViaDiameter() ) },
{ "microvia_drill", Iu2Millimeter( netclass->GetuViaDrill() ) },
{ "diff_pair_width", Iu2Millimeter( netclass->GetDiffPairWidth() ) },
{ "diff_pair_gap", Iu2Millimeter( netclass->GetDiffPairGap() ) },
{ "diff_pair_via_gap", Iu2Millimeter( netclass->GetDiffPairViaGap() ) }
};
nlohmann::json nets = nlohmann::json::array();
for( NETCLASS::const_iterator i = netclass->begin(); i != netclass->end(); ++i )
if( !i->empty() )
nets.push_back( std::string( i->ToUTF8() ) );
netJson["nets"] = nets;
ret.push_back( netJson );
}
return ret;
},
[&]( const nlohmann::json& aJson )
{
if( !aJson.is_array() )
return;
m_NetClasses.Clear();
NETCLASSPTR netclass;
NETCLASSPTR defaultClass = m_NetClasses.GetDefault();
auto get =
[]( const nlohmann::json& aObj, const std::string& aKey, int aDefault )
{
if( aObj.contains( aKey ) )
return Millimeter2iu( aObj[aKey].get<double>() );
else
return aDefault;
};
for( const nlohmann::json& entry : aJson )
{
if( !entry.is_object() || !entry.contains( "name" ) )
continue;
wxString name = entry["name"];
if( name == defaultClass->GetName() )
netclass = defaultClass;
else
netclass = std::make_shared<NETCLASS>( name );
netclass->SetClearance( get( aJson, "clearance", netclass->GetClearance() ) );
netclass->SetTrackWidth(
get( aJson, "track_width", netclass->GetTrackWidth() ) );
netclass->SetViaDiameter(
get( aJson, "via_diameter", netclass->GetViaDiameter() ) );
netclass->SetViaDrill( get( aJson, "via_drill", netclass->GetViaDrill() ) );
netclass->SetuViaDiameter(
get( aJson, "microvia_diameter", netclass->GetuViaDiameter() ) );
netclass->SetuViaDrill(
get( aJson, "microvia_drill", netclass->GetuViaDrill() ) );
netclass->SetDiffPairWidth(
get( aJson, "diff_pair_width", netclass->GetDiffPairWidth() ) );
netclass->SetDiffPairGap(
get( aJson, "diff_pair_gap", netclass->GetDiffPairGap() ) );
netclass->SetDiffPairViaGap(
get( aJson, "diff_pair_via_gap", netclass->GetDiffPairViaGap() ) );
if( netclass != defaultClass )
m_NetClasses.Add( netclass );
}
}, {} ) );
}
NET_SETTINGS::~NET_SETTINGS()
{
// Release early before destroying members
if( m_parent )
{
m_parent->ReleaseNestedSettings( this );
m_parent = nullptr;
}
}

View File

@ -0,0 +1,478 @@
/*
* 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 <config_params.h>
#include <project.h>
#include <project/net_settings.h>
#include <project/project_file.h>
#include <settings/common_settings.h>
#include <settings/parameters.h>
#include <wildcards_and_files_ext.h>
#include <wx/config.h>
#include <wx/log.h>
extern const char* traceSettings;
///! Update the schema version whenever a migration is required
const int projectFileSchemaVersion = 1;
PROJECT_FILE::PROJECT_FILE( const std::string& aFullPath ) :
JSON_SETTINGS( aFullPath, SETTINGS_LOC::PROJECT, projectFileSchemaVersion ),
m_sheets(), m_boards(), m_BoardSettings()
{
// Keep old files around
m_deleteLegacyAfterMigration = false;
m_params.emplace_back( new PARAM_LIST<FILE_INFO_PAIR>( "sheets", &m_sheets, {} ) );
m_params.emplace_back( new PARAM_LIST<FILE_INFO_PAIR>( "boards", &m_boards, {} ) );
m_params.emplace_back(
new PARAM_LIST<wxString>( "libraries.pinned_symbol_libs", &m_PinnedSymbolLibs, {} ) );
m_params.emplace_back( new PARAM_LIST<wxString>(
"libraries.pinned_footprint_libs", &m_PinnedFootprintLibs, {} ) );
m_params.emplace_back(
new PARAM_PATH_LIST( "cvpcb.equivalence_files", &m_EquivalenceFiles, {} ) );
m_params.emplace_back(
new PARAM_PATH( "pcbnew.page_layout_descr_file", &m_PageLayoutDescrFile, "" ) );
m_params.emplace_back(
new PARAM_PATH( "pcbnew.last_paths.netlist", &m_PcbLastPath[LAST_PATH_NETLIST], "" ) );
m_params.emplace_back(
new PARAM_PATH( "pcbnew.last_paths.step", &m_PcbLastPath[LAST_PATH_STEP], "" ) );
m_params.emplace_back(
new PARAM_PATH( "pcbnew.last_paths.idf", &m_PcbLastPath[LAST_PATH_IDF], "" ) );
m_params.emplace_back(
new PARAM_PATH( "pcbnew.last_paths.vmrl", &m_PcbLastPath[LAST_PATH_VRML], "" ) );
m_params.emplace_back( new PARAM_PATH(
"pcbnew.last_paths.specctra_dsn", &m_PcbLastPath[LAST_PATH_SPECCTRADSN], "" ) );
m_params.emplace_back(
new PARAM_PATH( "pcbnew.last_paths.gencad", &m_PcbLastPath[LAST_PATH_GENCAD], "" ) );
m_NetSettings = std::make_shared<NET_SETTINGS>( this, "net_settings" );
}
bool PROJECT_FILE::MigrateFromLegacy( wxConfigBase* aCfg )
{
bool ret = true;
wxString str;
long index = 0;
std::set<wxString> group_blacklist;
// Legacy files don't store board info; they assume board matches project name
// We will leave m_boards empty here so it can be populated with other code
// First handle migration of data that will be stored locally in this object
auto loadPinnedLibs =
[&]( const std::string& aDest )
{
int libIndex = 1;
wxString libKey = wxT( "PinnedItems" );
libKey << libIndex;
nlohmann::json libs = nlohmann::json::array();
while( aCfg->Read( libKey, &str ) )
{
libs.push_back( str );
aCfg->DeleteEntry( libKey, true );
libKey = wxT( "PinnedItems" );
libKey << ++libIndex;
}
( *this )[PointerFromString( aDest )] = libs;
};
aCfg->SetPath( wxT( "/LibeditFrame" ) );
loadPinnedLibs( "libraries.pinned_symbol_libs" );
aCfg->SetPath( wxT( "/ModEditFrame" ) );
loadPinnedLibs( "libraries.pinned_footprint_libs" );
aCfg->SetPath( wxT( "/cvpcb/equfiles" ) );
{
int eqIdx = 1;
wxString eqKey = wxT( "EquName" );
eqKey << eqIdx;
nlohmann::json eqs = nlohmann::json::array();
while( aCfg->Read( eqKey, &str ) )
{
eqs.push_back( str );
eqKey = wxT( "EquName" );
eqKey << ++eqIdx;
}
( *this )[PointerFromString( "cvpcb.equivalence_files" )] = eqs;
}
// All CvPcb params that we want to keep have been migrated above
group_blacklist.insert( wxT( "/cvpcb" ) );
aCfg->SetPath( wxT( "/pcbnew" ) );
fromLegacyString( aCfg, "PageLayoutDescrFile", "pcbnew.page_layout_descr_file" );
fromLegacyString( aCfg, "LastNetListRead", "pcbnew.last_paths.netlist" );
fromLegacyString( aCfg, "LastSTEPExportPath", "pcbnew.last_paths.step" );
fromLegacyString( aCfg, "LastIDFExportPath", "pcbnew.last_paths.idf" );
fromLegacyString( aCfg, "LastVRMLExportPath", "pcbnew.last_paths.vmrl" );
fromLegacyString( aCfg, "LastSpecctraDSNExportPath", "pcbnew.last_paths.specctra_dsn" );
fromLegacyString( aCfg, "LastGenCADExportPath", "pcbnew.last_paths.gencad" );
std::string bp = "board.design_settings.";
{
int idx = 1;
wxString key = wxT( "DRCExclusion" );
key << idx;
nlohmann::json exclusions = nlohmann::json::array();
while( aCfg->Read( key, &str ) )
{
exclusions.push_back( str );
key = wxT( "DRCExclusion" );
key << ++idx;
}
( *this )[PointerFromString( bp + "drc_exclusions" )] = exclusions;
}
fromLegacy<bool>( aCfg, "AllowMicroVias", bp + "rules.allow_microvias" );
fromLegacy<bool>( aCfg, "AllowBlindVias", bp + "rules.allow_blind_buried_vias" );
fromLegacy<double>( aCfg, "MinClearance", bp + "rules.min_clearance" );
fromLegacy<double>( aCfg, "MinTrackWidth", bp + "rules.min_track_width" );
fromLegacy<double>( aCfg, "MinViaAnnulus", bp + "rules.min_via_annulus" );
fromLegacy<double>( aCfg, "MinViaDiameter", bp + "rules.min_via_diameter" );
if( !fromLegacy<double>( aCfg, "MinThroughDrill", bp + "rules.min_through_hole_diameter" ) )
fromLegacy<double>( aCfg, "MinViaDrill", bp + "rules.min_through_hole_diameter" );
fromLegacy<double>( aCfg, "MinMicroViaDiameter", bp + "rules.min_microvia_diameter" );
fromLegacy<double>( aCfg, "MinMicroViaDrill", bp + "rules.min_microvia_drill" );
fromLegacy<double>( aCfg, "MinHoleToHole", bp + "rules.min_hole_to_hole" );
fromLegacy<double>( aCfg, "CopperEdgeClearance", bp + "rules.min_copper_edge_clearance" );
fromLegacy<double>( aCfg, "SolderMaskClearance", bp + "rules.solder_mask_clearance" );
fromLegacy<double>( aCfg, "SolderMaskMinWidth", bp + "rules.solder_mask_min_width" );
fromLegacy<double>( aCfg, "SolderPasteClearance", bp + "rules.solder_paste_clearance" );
fromLegacy<double>( aCfg, "SolderPasteRatio", bp + "rules.solder_paste_margin_ratio" );
if( !fromLegacy<double>( aCfg, "SilkLineWidth", bp + "defaults.silk_line_width" ) )
fromLegacy<double>( aCfg, "ModuleOutlineThickness", bp + "defaults.silk_line_width" );
if( !fromLegacy<double>( aCfg, "SilkTextSizeV", bp + "defaults.silk_text_size_v" ) )
fromLegacy<double>( aCfg, "ModuleTextSizeV", bp + "defaults.silk_text_size_v" );
if( !fromLegacy<double>( aCfg, "SilkTextSizeH", bp + "defaults.silk_text_size_h" ) )
fromLegacy<double>( aCfg, "ModuleTextSizeH", bp + "defaults.silk_text_size_h" );
if( !fromLegacy<double>( aCfg, "SilkTextSizeThickness", bp + "defaults.silk_text_thickness" ) )
fromLegacy<double>( aCfg, "ModuleTextSizeThickness", bp + "defaults.silk_text_thickness" );
fromLegacy<bool>( aCfg, "SilkTextItalic", bp + "defaults.silk_text_italic" );
fromLegacy<bool>( aCfg, "SilkTextUpright", bp + "defaults.silk_text_upright" );
if( !fromLegacy<double>( aCfg, "CopperLineWidth", bp + "defaults.copper_line_width" ) )
fromLegacy<double>( aCfg, "DrawSegmentWidth", bp + "defaults.copper_line_width" );
if( !fromLegacy<double>( aCfg, "CopperTextSizeV", bp + "defaults.copper_text_size_v" ) )
fromLegacy<double>( aCfg, "PcbTextSizeV", bp + "defaults.copper_text_size_v" );
if( !fromLegacy<double>( aCfg, "CopperTextSizeH", bp + "defaults.copper_text_size_h" ) )
fromLegacy<double>( aCfg, "PcbTextSizeH", bp + "defaults.copper_text_size_h" );
if( !fromLegacy<double>( aCfg, "CopperTextThickness", bp + "defaults.copper_text_thickness" ) )
fromLegacy<double>( aCfg, "PcbTextThickness", bp + "defaults.copper_text_thickness" );
fromLegacy<bool>( aCfg, "CopperTextItalic", bp + "defaults.copper_text_italic" );
fromLegacy<bool>( aCfg, "CopperTextUpright", bp + "defaults.copper_text_upright" );
if( !fromLegacy<double>( aCfg, "EdgeCutLineWidth", bp + "defaults.board_outline_line_width" ) )
fromLegacy<double>(
aCfg, "BoardOutlineThickness", bp + "defaults.board_outline_line_width" );
fromLegacy<double>( aCfg, "CourtyardLineWidth", bp + "defaults.courtyard_line_width" );
fromLegacy<double>( aCfg, "FabLineWidth", bp + "defaults.fab_line_width" );
fromLegacy<double>( aCfg, "FabTextSizeV", bp + "defaults.fab_text_size_v" );
fromLegacy<double>( aCfg, "FabTextSizeH", bp + "defaults.fab_text_size_h" );
fromLegacy<double>( aCfg, "FabTextSizeThickness", bp + "defaults.fab_text_thickness" );
fromLegacy<bool>( aCfg, "FabTextItalic", bp + "defaults.fab_text_italic" );
fromLegacy<bool>( aCfg, "FabTextUpright", bp + "defaults.fab_text_upright" );
if( !fromLegacy<double>( aCfg, "OthersLineWidth", bp + "defaults.other_line_width" ) )
fromLegacy<double>( aCfg, "ModuleOutlineThickness", bp + "defaults.other_line_width" );
fromLegacy<double>( aCfg, "OthersTextSizeV", bp + "defaults.other_text_size_v" );
fromLegacy<double>( aCfg, "OthersTextSizeH", bp + "defaults.other_text_size_h" );
fromLegacy<double>( aCfg, "OthersTextSizeThickness", bp + "defaults.other_text_thickness" );
fromLegacy<bool>( aCfg, "OthersTextItalic", bp + "defaults.other_text_italic" );
fromLegacy<bool>( aCfg, "OthersTextUpright", bp + "defaults.other_text_upright" );
fromLegacy<int>( aCfg, "DimensionUnits", bp + "defaults.dimension_units" );
fromLegacy<int>( aCfg, "DimensionPrecision", bp + "defaults.dimension_precision" );
std::string sev = bp + "rule_severities";
fromLegacy<bool>(
aCfg, "RequireCourtyardDefinitions", sev + "legacy_no_courtyard_defined" );
fromLegacy<bool>( aCfg, "ProhibitOverlappingCourtyards", sev + "legacy_ourtyards_overlap" );
{
int idx = 1;
wxString keyBase = "TrackWidth";
wxString key = keyBase;
double val;
nlohmann::json widths = nlohmann::json::array();
key << idx;
while( aCfg->Read( key, &val ) )
{
widths.push_back( val );
key = keyBase;
key << ++idx;
}
( *this )[PointerFromString( bp + "track_widths" )] = widths;
}
{
int idx = 1;
wxString keyBase = "ViaDiameter";
wxString key = keyBase;
double diameter;
double drill = 1.0;
nlohmann::json vias = nlohmann::json::array();
key << idx;
while( aCfg->Read( key, &diameter ) )
{
key = "ViaDrill";
aCfg->Read( key << idx, &drill );
nlohmann::json via = { { "diameter", diameter }, { "drill", drill } };
vias.push_back( via );
key = keyBase;
key << ++idx;
}
( *this )[PointerFromString( bp + "via_dimensions" )] = vias;
}
{
int idx = 1;
wxString keyBase = "dPairWidth";
wxString key = keyBase;
double width;
double gap = 1.0;
double via_gap = 1.0;
nlohmann::json pairs = nlohmann::json::array();
key << idx;
while( aCfg->Read( key, &width ) )
{
key = "dPairGap";
aCfg->Read( key << idx, &gap );
key = "dPairViaGap";
aCfg->Read( key << idx, &via_gap );
nlohmann::json pair = { { "width", width }, { "gap", gap }, { "via_gap", via_gap } };
pairs.push_back( pair );
key = keyBase;
key << ++idx;
}
( *this )[PointerFromString( bp + "diff_pair_dimensions" )] = pairs;
}
// NOTE: severities are just left alone to be migrated by BOARD_DESIGN_SETTINGS when it
// initializes, so that common doesn't need knowledge of the DRC error list (this is the
// downside of storing them as string keys... Do not blacklist the /pcbnew group so that
// this works!
// General group is unused these days, we can throw it away
group_blacklist.insert( wxT( "/general" ) );
// Next load sheet names and put all other legacy data in the legacy dict
aCfg->SetPath( wxT( "/" ) );
auto loadSheetNames =
[&]() -> bool
{
int sheet = 1;
wxString entry;
nlohmann::json arr = nlohmann::json::array();
wxLogTrace( traceSettings, "Migrating sheet names" );
aCfg->SetPath( wxT( "/sheetnames" ) );
while( aCfg->Read( wxString::Format( "%d", sheet++ ), &entry ) )
{
wxArrayString tokens = wxSplit( entry, ':' );
if( tokens.size() == 2 )
{
wxLogTrace( traceSettings, "%d: %s = %s", sheet, tokens[0], tokens[1] );
arr.push_back( nlohmann::json::array( { tokens[0], tokens[1] } ) );
}
}
( *this )[PointerFromString( "sheets" )] = arr;
aCfg->SetPath( "/" );
// TODO: any reason we want to fail on this?
return true;
};
std::vector<wxString> groups;
groups.emplace_back( "" );
auto loadLegacyPairs =
[&]( const std::string& aGroup ) -> bool
{
wxLogTrace( traceSettings, "Migrating group %s", aGroup );
bool success = true;
wxString keyStr;
wxString val;
index = 0;
while( aCfg->GetNextEntry( keyStr, index ) )
{
if( !aCfg->Read( keyStr, &val ) )
continue;
std::string key( keyStr.ToUTF8() );
wxLogTrace( traceSettings, " %s = %s", key, val );
try
{
nlohmann::json::json_pointer ptr( "/legacy" + aGroup + "/" + key );
( *this )[ptr] = val;
}
catch( ... )
{
success = false;
}
}
return success;
};
for( size_t i = 0; i < groups.size(); i++ )
{
aCfg->SetPath( groups[i] );
if( groups[i] == wxT( "/sheetnames" ) )
{
ret |= loadSheetNames();
continue;
}
aCfg->DeleteEntry( wxT( "last_client" ), true );
aCfg->DeleteEntry( wxT( "update" ), true );
aCfg->DeleteEntry( wxT( "version" ), true );
ret &= loadLegacyPairs( groups[i].ToStdString() );
index = 0;
while( aCfg->GetNextGroup( str, index ) )
{
wxString group = groups[i] + "/" + str;
if( !group_blacklist.count( group ) )
groups.emplace_back( group );
}
aCfg->SetPath( "/" );
}
return ret;
}
bool PROJECT_FILE::SaveToFile( const std::string& aDirectory, bool aForce )
{
wxASSERT( m_project );
( *this )[PointerFromString( "meta.filename" )] =
m_project->GetProjectName() + "." + ProjectFileExtension;
return JSON_SETTINGS::SaveToFile( aDirectory, aForce );
}
wxString PROJECT_FILE::getFileExt() const
{
return ProjectFileExtension;
}
wxString PROJECT_FILE::getLegacyFileExt() const
{
return LegacyProjectFileExtension;
}
void to_json( nlohmann::json& aJson, const FILE_INFO_PAIR& aPair )
{
aJson = nlohmann::json::array( { aPair.first.AsString().ToUTF8(), aPair.second.ToUTF8() } );
}
void from_json( const nlohmann::json& aJson, FILE_INFO_PAIR& aPair )
{
wxASSERT( aJson.is_array() && aJson.size() == 2 );
aPair.first = KIID( wxString( aJson[0].get<std::string>().c_str(), wxConvUTF8 ) );
aPair.second = wxString( aJson[1].get<std::string>().c_str(), wxConvUTF8 );
}

View File

@ -0,0 +1,105 @@
/*
* 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 = 1;
PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( const std::string& aFilename ) :
JSON_SETTINGS( aFilename, SETTINGS_LOC::PROJECT, projectLocalSettingsVersion,
/* aCreateIfMissing = */ true, /* aCreateIfDefault = */ false,
/* aWriteFile = */ true ),
m_project( nullptr )
{
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() ) );
static GAL_SET defaultVisible;
defaultVisible.set().reset( GAL_LAYER_INDEX( LAYER_MOD_TEXT_INVISIBLE ) );
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 = 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
}
}
},
{} ) );
}
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 std::string& aDirectory, bool aForce )
{
wxASSERT( m_project );
( *this )[PointerFromString( "meta.filename" )] =
m_project->GetProjectName() + "." + ProjectLocalSettingsFileExtension;
return JSON_SETTINGS::SaveToFile( aDirectory, aForce );
}

View File

@ -46,11 +46,11 @@ JSON_SETTINGS::JSON_SETTINGS( const std::string& aFilename, SETTINGS_LOC aLocati
m_createIfDefault( aCreateIfDefault ),
m_writeFile( aWriteFile ),
m_deleteLegacyAfterMigration( true ),
m_resetParamsIfMissing( true ),
m_schemaVersion( aSchemaVersion ),
m_manager( nullptr )
{
m_params.emplace_back(
new PARAM<std::string>( "meta.filename", &m_filename, m_filename, true ) );
( *this )[PointerFromString( "meta.filename" )] = GetFullFilename();
m_params.emplace_back(
new PARAM<int>( "meta.version", &m_schemaVersion, m_schemaVersion, true ) );
@ -66,13 +66,19 @@ JSON_SETTINGS::~JSON_SETTINGS()
}
wxString JSON_SETTINGS::GetFullFilename() const
{
return wxString( m_filename.c_str(), wxConvUTF8 ) + "." + getFileExt();
}
void JSON_SETTINGS::Load()
{
for( auto param : m_params )
{
try
{
param->Load( this );
param->Load( this, m_resetParamsIfMissing );
}
catch( ... )
{
@ -106,7 +112,8 @@ bool JSON_SETTINGS::LoadFromFile( const std::string& aDirectory )
if( !wxCopyFile( aPath.GetFullPath(), temp.GetFullPath() ) )
{
wxLogTrace( traceSettings, "%s: could not create temp file for migration", m_filename );
wxLogTrace( traceSettings, "%s: could not create temp file for migration",
GetFullFilename() );
backed_up = false;
}
@ -118,11 +125,12 @@ bool JSON_SETTINGS::LoadFromFile( const std::string& aDirectory )
if( !MigrateFromLegacy( cfg.get() ) )
{
wxLogTrace( traceSettings,
"%s: migrated; not all settings were found in legacy file", m_filename );
"%s: migrated; not all settings were found in legacy file",
GetFullFilename() );
}
else
{
wxLogTrace( traceSettings, "%s: migrated from legacy format", m_filename );
wxLogTrace( traceSettings, "%s: migrated from legacy format", GetFullFilename() );
}
if( backed_up )
@ -186,14 +194,15 @@ bool JSON_SETTINGS::LoadFromFile( const std::string& aDirectory )
}
catch( ... )
{
wxLogTrace( traceSettings, "%s: file version could not be read!", m_filename );
wxLogTrace(
traceSettings, "%s: file version could not be read!", GetFullFilename() );
success = false;
}
if( filever >= 0 && filever < m_schemaVersion )
{
wxLogTrace( traceSettings, "%s: attempting migration from version %d to %d",
m_filename, filever, m_schemaVersion );
GetFullFilename(), filever, m_schemaVersion );
if( Migrate() )
{
@ -201,13 +210,13 @@ bool JSON_SETTINGS::LoadFromFile( const std::string& aDirectory )
}
else
{
wxLogTrace( traceSettings, "%s: migration failed!", m_filename );
wxLogTrace( traceSettings, "%s: migration failed!", GetFullFilename() );
}
}
else if( filever > m_schemaVersion )
{
wxLogTrace( traceSettings,
"%s: warning: file version %d is newer than latest (%d)", m_filename,
"%s: warning: file version %d is newer than latest (%d)", GetFullFilename(),
filever, m_schemaVersion );
}
}
@ -227,7 +236,7 @@ bool JSON_SETTINGS::LoadFromFile( const std::string& aDirectory )
for( auto settings : m_nested_settings )
settings->LoadFromFile();
wxLogTrace( traceSettings, "Loaded %s with schema %d", GetFilename(), m_schemaVersion );
wxLogTrace( traceSettings, "Loaded %s with schema %d", GetFullFilename(), m_schemaVersion );
// If we migrated, clean up the legacy file (with no extension)
if( legacy_migrated || migrated )
@ -292,7 +301,7 @@ bool JSON_SETTINGS::SaveToFile( const std::string& aDirectory, bool aForce )
{
wxLogTrace( traceSettings,
"File for %s doesn't exist and m_createIfMissing == false; not saving",
m_filename );
GetFullFilename() );
return false;
}
@ -305,27 +314,25 @@ bool JSON_SETTINGS::SaveToFile( const std::string& aDirectory, bool aForce )
if( !modified && !aForce && path.FileExists() )
{
wxLogTrace( traceSettings, "%s contents not modified, skipping save", m_filename );
wxLogTrace( traceSettings, "%s contents not modified, skipping save", GetFullFilename() );
return false;
}
else if( !modified && !aForce && !m_createIfDefault )
{
wxLogTrace( traceSettings,
"%s contents still default and m_createIfDefault == false; not saving",
m_filename );
GetFullFilename() );
return false;
}
wxLogTrace( traceSettings, "Saving %s", m_filename );
if( !path.DirExists() && !path.Mkdir() )
{
wxLogTrace( traceSettings, "Warning: could not create path %s, can't save %s",
path.GetPath(), m_filename );
path.GetPath(), GetFullFilename() );
return false;
}
wxLogTrace( traceSettings, "Saving %s", m_filename );
wxLogTrace( traceSettings, "Saving %s", GetFullFilename() );
LOCALE_IO dummy;
@ -336,7 +343,7 @@ bool JSON_SETTINGS::SaveToFile( const std::string& aDirectory, bool aForce )
}
catch( const std::exception& e )
{
wxLogTrace( traceSettings, "Warning: could not save %s: %s", m_filename, e.what() );
wxLogTrace( traceSettings, "Warning: could not save %s: %s", GetFullFilename(), e.what() );
}
catch( ... )
{
@ -346,9 +353,9 @@ bool JSON_SETTINGS::SaveToFile( const std::string& aDirectory, bool aForce )
}
OPT<nlohmann::json> JSON_SETTINGS::GetJson( std::string aPath ) const
OPT<nlohmann::json> JSON_SETTINGS::GetJson( const std::string& aPath ) const
{
nlohmann::json::json_pointer ptr = PointerFromString( std::move( aPath ) );
nlohmann::json::json_pointer ptr = PointerFromString( aPath );
if( this->contains( ptr ) )
{
@ -498,6 +505,9 @@ void JSON_SETTINGS::AddNestedSettings( NESTED_SETTINGS* aSettings )
void JSON_SETTINGS::ReleaseNestedSettings( NESTED_SETTINGS* aSettings )
{
if( !aSettings )
return;
auto it = std::find_if( m_nested_settings.begin(), m_nested_settings.end(),
[&aSettings]( const JSON_SETTINGS* aPtr ) {
return aPtr == aSettings;
@ -509,21 +519,23 @@ void JSON_SETTINGS::ReleaseNestedSettings( NESTED_SETTINGS* aSettings )
( *it )->SaveToFile();
m_nested_settings.erase( it );
}
aSettings->SetParent( nullptr );
}
// Specializations to allow conversion between wxString and std::string via JSON_SETTINGS API
template<> OPT<wxString> JSON_SETTINGS::Get( std::string aPath ) const
template<> OPT<wxString> JSON_SETTINGS::Get( const std::string& aPath ) const
{
if( OPT<nlohmann::json> opt_json = GetJson( std::move( aPath ) ) )
if( OPT<nlohmann::json> opt_json = GetJson( aPath ) )
return wxString( opt_json->get<std::string>().c_str(), wxConvUTF8 );
return NULLOPT;
}
template<> void JSON_SETTINGS::Set<wxString>( std::string aPath, wxString aVal )
template<> void JSON_SETTINGS::Set<wxString>( const std::string& aPath, wxString aVal )
{
( *this )[PointerFromString( std::move( aPath ) ) ] = aVal.ToUTF8();
}

View File

@ -30,19 +30,14 @@ NESTED_SETTINGS::NESTED_SETTINGS( const std::string& aName, int aVersion, JSON_S
JSON_SETTINGS( aName, SETTINGS_LOC::NESTED, aVersion ),
m_parent( aParent ), m_path( aPath )
{
if( m_parent )
{
m_parent->AddNestedSettings( this );
}
// In case we were created after the parent's ctor
LoadFromFile();
SetParent( aParent );
}
NESTED_SETTINGS::~NESTED_SETTINGS()
{
m_parent->ReleaseNestedSettings( this );
if( m_parent )
m_parent->ReleaseNestedSettings( this );
}
@ -77,6 +72,9 @@ bool NESTED_SETTINGS::LoadFromFile( const std::string& aDirectory )
bool NESTED_SETTINGS::SaveToFile( const std::string& aDirectory, bool aForce )
{
if( !m_parent )
return false;
bool modified = Store();
try
@ -108,3 +106,15 @@ bool NESTED_SETTINGS::SaveToFile( const std::string& aDirectory, bool aForce )
return modified;
}
void NESTED_SETTINGS::SetParent( JSON_SETTINGS* aParent )
{
m_parent = aParent;
if( m_parent )
m_parent->AddNestedSettings( this );
// In case we were created after the parent's ctor
LoadFromFile();
}

View File

@ -1,247 +0,0 @@
/*
* 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 <config_params.h>
#include <settings/common_settings.h>
#include <settings/parameters.h>
#include <settings/project_file.h>
#include <wildcards_and_files_ext.h>
#include <wx/config.h>
#include <wx/log.h>
extern const char* traceSettings;
///! Update the schema version whenever a migration is required
const int projectFileSchemaVersion = 1;
PROJECT_FILE::PROJECT_FILE( const std::string& aFullPath ) :
JSON_SETTINGS( aFullPath, SETTINGS_LOC::NONE, projectFileSchemaVersion ),
m_sheets(), m_boards()
{
// Keep old files around
m_deleteLegacyAfterMigration = false;
m_params.emplace_back( new PARAM_LIST<FILE_INFO_PAIR>( "sheets", &m_sheets, {} ) );
m_params.emplace_back( new PARAM_LIST<FILE_INFO_PAIR>( "boards", &m_boards, {} ) );
m_params.emplace_back(
new PARAM_LIST<wxString>( "libraries.pinned_symbol_libs", &m_PinnedSymbolLibs, {} ) );
m_params.emplace_back( new PARAM_LIST<wxString>(
"libraries.pinned_footprint_libs", &m_PinnedFootprintLibs, {} ) );
m_params.emplace_back(
new PARAM_PATH_LIST( "cvpcb.equivalence_files", &m_EquivalenceFiles, {} ) );
}
bool PROJECT_FILE::MigrateFromLegacy( wxConfigBase* aLegacyFile )
{
bool ret = true;
wxString str;
long index = 0;
std::set<wxString> group_blacklist;
// Legacy files don't store board info; they assume board matches project name
// We will leave m_boards empty here so it can be populated with other code
// First handle migration of data that will be stored locally in this object
auto loadPinnedLibs =
[&]( const std::string& aDest )
{
int libIndex = 1;
wxString libKey = wxT( "PinnedItems" );
libKey << libIndex;
nlohmann::json libs = nlohmann::json::array();
while( aLegacyFile->Read( libKey, &str ) )
{
libs.push_back( str );
aLegacyFile->DeleteEntry( libKey, true );
libKey = wxT( "PinnedItems" );
libKey << ++libIndex;
}
( *this )[PointerFromString( aDest )] = libs;
};
aLegacyFile->SetPath( wxT( "/LibeditFrame" ) );
loadPinnedLibs( "libraries.pinned_symbol_libs" );
aLegacyFile->SetPath( wxT( "/ModEditFrame" ) );
loadPinnedLibs( "libraries.pinned_footprint_libs" );
aLegacyFile->SetPath( wxT( "/cvpcb/equfiles" ) );
{
int eqIdx = 1;
wxString eqKey = wxT( "EquName" );
eqKey << eqIdx;
nlohmann::json eqs = nlohmann::json::array();
while( aLegacyFile->Read( eqKey, &str ) )
{
eqs.push_back( str );
eqKey = wxT( "EquName" );
eqKey << ++eqIdx;
}
( *this )[PointerFromString( "cvpcb.equivalence_files" )] = eqs;
}
// No other cvpcb params are currently used
group_blacklist.insert( "/cvpcb" );
// Next load sheet names and put all other legacy data in the legacy dict
aLegacyFile->SetPath( "/" );
auto loadSheetNames =
[&]() -> bool
{
int sheet = 1;
wxString entry;
nlohmann::json arr = nlohmann::json::array();
wxLogTrace( traceSettings, "Migrating sheet names" );
aLegacyFile->SetPath( wxT( "/sheetnames" ) );
while( aLegacyFile->Read( wxString::Format( "%d", sheet++ ), &entry ) )
{
wxArrayString tokens = wxSplit( entry, ':' );
if( tokens.size() == 2 )
{
wxLogTrace( traceSettings, "%d: %s = %s", sheet, tokens[0], tokens[1] );
arr.push_back( nlohmann::json::array( { tokens[0], tokens[1] } ) );
}
}
( *this )[PointerFromString( "sheets" )] = arr;
aLegacyFile->SetPath( "/" );
// TODO: any reason we want to fail on this?
return true;
};
std::vector<wxString> groups;
groups.emplace_back( "" );
auto loadLegacyPairs =
[&]( const std::string& aGroup ) -> bool
{
wxLogTrace( traceSettings, "Migrating group %s", aGroup );
bool success = true;
wxString keyStr;
wxString val;
index = 0;
while( aLegacyFile->GetNextEntry( keyStr, index ) )
{
if( !aLegacyFile->Read( keyStr, &val ) )
continue;
std::string key( keyStr.ToUTF8() );
wxLogTrace( traceSettings, " %s = %s", key, val );
try
{
nlohmann::json::json_pointer ptr( "/legacy" + aGroup + "/" + key );
( *this )[ptr] = val;
}
catch( ... )
{
success = false;
}
}
return success;
};
for( size_t i = 0; i < groups.size(); i++ )
{
aLegacyFile->SetPath( groups[i] );
if( groups[i] == wxT( "/sheetnames" ) )
{
ret |= loadSheetNames();
continue;
}
aLegacyFile->DeleteEntry( wxT( "last_client" ), true );
aLegacyFile->DeleteEntry( wxT( "update" ), true );
aLegacyFile->DeleteEntry( wxT( "version" ), true );
ret &= loadLegacyPairs( groups[i].ToStdString() );
index = 0;
while( aLegacyFile->GetNextGroup( str, index ) )
{
wxString group = groups[i] + "/" + str;
if( !group_blacklist.count( group ) )
groups.emplace_back( group );
}
aLegacyFile->SetPath( "/" );
}
return ret;
}
wxString PROJECT_FILE::getFileExt() const
{
return ProjectFileExtension;
}
wxString PROJECT_FILE::getLegacyFileExt() const
{
return LegacyProjectFileExtension;
}
void to_json( nlohmann::json& aJson, const FILE_INFO_PAIR& aPair )
{
aJson = nlohmann::json::array( { aPair.first.AsString().ToUTF8(), aPair.second.ToUTF8() } );
}
void from_json( const nlohmann::json& aJson, FILE_INFO_PAIR& aPair )
{
wxASSERT( aJson.is_array() && aJson.size() == 2 );
aPair.first = KIID( wxString( aJson[0].get<std::string>().c_str(), wxConvUTF8 ) );
aPair.second = wxString( aJson[1].get<std::string>().c_str(), wxConvUTF8 );
}

View File

@ -30,10 +30,11 @@
#include <gestfich.h>
#include <macros.h>
#include <project.h>
#include <project/project_file.h>
#include <project/project_local_settings.h>
#include <settings/app_settings.h>
#include <settings/color_settings.h>
#include <settings/common_settings.h>
#include <settings/project_file.h>
#include <settings/settings_manager.h>
#include <wildcards_and_files_ext.h>
@ -46,7 +47,7 @@ const char* traceSettings = "SETTINGS";
/// Project settings path will be <projectname> + this
#define PROJECT_SETTINGS_DIR_SUFFIX wxT( "-settings" )
#define PROJECT_BACKUPS_DIR_SUFFIX wxT( "-backups" )
SETTINGS_MANAGER::SETTINGS_MANAGER() :
@ -83,7 +84,7 @@ JSON_SETTINGS* SETTINGS_MANAGER::RegisterSettings( JSON_SETTINGS* aSettings, boo
ptr->SetManager( this );
wxLogTrace( traceSettings, "Registered new settings object %s", ptr->GetFilename() );
wxLogTrace( traceSettings, "Registered new settings object %s", ptr->GetFullFilename() );
if( aLoadNow )
ptr->LoadFromFile( GetPathForSettingsFile( ptr.get() ) );
@ -139,13 +140,13 @@ void SETTINGS_MANAGER::Save( JSON_SETTINGS* aSettings )
if( it != m_settings.end() )
{
wxLogTrace( traceSettings, "Saving %s", ( *it )->GetFilename() );
wxLogTrace( traceSettings, "Saving %s", ( *it )->GetFullFilename() );
( *it )->SaveToFile( GetPathForSettingsFile( it->get() ) );
}
}
void SETTINGS_MANAGER::FlushAndRelease( JSON_SETTINGS* aSettings )
void SETTINGS_MANAGER::FlushAndRelease( JSON_SETTINGS* aSettings, bool aSave )
{
auto it = std::find_if( m_settings.begin(), m_settings.end(),
[&aSettings]( const std::unique_ptr<JSON_SETTINGS>& aPtr )
@ -155,8 +156,11 @@ void SETTINGS_MANAGER::FlushAndRelease( JSON_SETTINGS* aSettings )
if( it != m_settings.end() )
{
wxLogTrace( traceSettings, "Flush and release %s", ( *it )->GetFilename() );
( *it )->SaveToFile( GetPathForSettingsFile( it->get() ) );
wxLogTrace( traceSettings, "Flush and release %s", ( *it )->GetFullFilename() );
if( aSave )
( *it )->SaveToFile( GetPathForSettingsFile( it->get() ) );
m_settings.erase( it );
}
}
@ -332,8 +336,7 @@ std::string SETTINGS_MANAGER::GetPathForSettingsFile( JSON_SETTINGS* aSettings )
return GetUserSettingsPath();
case SETTINGS_LOC::PROJECT:
// TODO(JE)
return "";
return std::string( Prj().GetProjectPath().ToUTF8() );
case SETTINGS_LOC::COLORS:
return GetColorSettingsPath();
@ -667,7 +670,7 @@ bool SETTINGS_MANAGER::extractVersion( const std::string& aVersionString, int* a
}
bool SETTINGS_MANAGER::LoadProject( const wxString& aFullPath )
bool SETTINGS_MANAGER::LoadProject( const wxString& aFullPath, bool aSetActive )
{
// Normalize path to new format even if migrating from a legacy file
wxFileName path( aFullPath );
@ -678,33 +681,45 @@ bool SETTINGS_MANAGER::LoadProject( const wxString& aFullPath )
wxString fullPath = path.GetFullPath();
// Unload if already loaded
if( m_projects.count( fullPath ) && !UnloadProject( *m_projects.at( fullPath ).get() ) )
if( m_projects.count( fullPath ) && !UnloadProject( m_projects.at( fullPath ).get() ) )
return false;
// No MDI yet
if( !m_projects.empty() && !UnloadProject( *m_projects.begin()->second ) )
if( aSetActive && !m_projects.empty() && !UnloadProject( m_projects.begin()->second.get() ) )
return false;
wxLogTrace( traceSettings, "Load project %s", fullPath );
m_projects[fullPath] = std::make_unique<PROJECT>();
m_projects[fullPath]->setProjectFullName( fullPath );
std::unique_ptr<PROJECT> project = std::make_unique<PROJECT>();
project->setProjectFullName( fullPath );
return loadProjectFile( *m_projects[fullPath] );
bool success = loadProjectFile( *project );
m_projects[fullPath].reset( project.release() );
std::string fn( path.GetName() );
PROJECT_LOCAL_SETTINGS* settings = static_cast<PROJECT_LOCAL_SETTINGS*>(
RegisterSettings( new PROJECT_LOCAL_SETTINGS( fn ) ) );
m_projects[fullPath]->setLocalSettings( settings );
settings->SetProject( m_projects[fullPath].get() );
return success;
}
bool SETTINGS_MANAGER::UnloadProject( PROJECT& aProject )
bool SETTINGS_MANAGER::UnloadProject( PROJECT* aProject, bool aSave )
{
if( !m_projects.count( aProject.GetProjectFullName() ) )
if( !aProject || !m_projects.count( aProject->GetProjectFullName() ) )
return false;
if( !unloadProjectFile( aProject ) )
if( !unloadProjectFile( aProject, aSave ) )
return false;
wxLogTrace( traceSettings, "Unload project %s", aProject.GetProjectFullName() );
wxLogTrace( traceSettings, "Unload project %s", aProject->GetProjectFullName() );
m_projects.erase( aProject.GetProjectFullName() );
m_projects.erase( aProject->GetProjectFullName() );
return true;
}
@ -712,34 +727,50 @@ bool SETTINGS_MANAGER::UnloadProject( PROJECT& aProject )
PROJECT& SETTINGS_MANAGER::Prj() const
{
// No MDI yet
wxASSERT( m_projects.size() == 1 );
// No MDI yet: First project in the list is the active project
return *m_projects.begin()->second;
}
bool SETTINGS_MANAGER::SaveProject()
PROJECT* SETTINGS_MANAGER::GetProject( const wxString& aFullPath ) const
{
wxString name = Prj().GetProjectFullName();
if( m_projects.count( aFullPath ) )
return m_projects.at( aFullPath ).get();
if( !m_project_files.count( name ) )
return nullptr;
}
bool SETTINGS_MANAGER::SaveProject( const wxString& aFullPath )
{
wxString path = aFullPath;
if( path.empty() )
path = Prj().GetProjectFullName();
if( !m_project_files.count( path ) )
return false;
m_project_files[name]->SaveToFile();
PROJECT_FILE* project = m_project_files.at( path );
std::string projectPath = GetPathForSettingsFile( project );
project->SaveToFile( projectPath );
Prj().GetLocalSettings().SaveToFile( projectPath );
return true;
}
wxString SETTINGS_MANAGER::GetProjectSettingsPath() const
wxString SETTINGS_MANAGER::GetProjectBackupsPath() const
{
return Prj().GetProjectPath() + Prj().GetProjectName() + PROJECT_SETTINGS_DIR_SUFFIX;
return Prj().GetProjectPath() + Prj().GetProjectName() + PROJECT_BACKUPS_DIR_SUFFIX;
}
bool SETTINGS_MANAGER::loadProjectFile( PROJECT& aProject )
{
std::string fn( aProject.GetProjectFullName().ToUTF8() );
wxFileName fullFn( aProject.GetProjectFullName() );
std::string fn( fullFn.GetName().ToUTF8() );
PROJECT_FILE* file =
static_cast<PROJECT_FILE*>( RegisterSettings( new PROJECT_FILE( fn ), false ) );
@ -747,14 +778,18 @@ bool SETTINGS_MANAGER::loadProjectFile( PROJECT& aProject )
m_project_files[aProject.GetProjectFullName()] = file;
aProject.setProjectFile( file );
file->SetProject( &aProject );
return file->LoadFromFile();
return file->LoadFromFile( std::string( fullFn.GetPath().ToUTF8() ) );
}
bool SETTINGS_MANAGER::unloadProjectFile( PROJECT& aProject )
bool SETTINGS_MANAGER::unloadProjectFile( PROJECT* aProject, bool aSave )
{
wxString name = aProject.GetProjectFullName();
if( !aProject )
return false;
wxString name = aProject->GetProjectFullName();
if( !m_project_files.count( name ) )
return false;
@ -769,7 +804,13 @@ bool SETTINGS_MANAGER::unloadProjectFile( PROJECT& aProject )
if( it != m_settings.end() )
{
( *it )->SaveToFile();
std::string projectPath = GetPathForSettingsFile( it->get() );
FlushAndRelease( &aProject->GetLocalSettings(), aSave );
if( aSave )
( *it )->SaveToFile( projectPath );
m_settings.erase( it );
}

View File

@ -122,6 +122,7 @@ const std::string VrmlFileExtension( "wrl" );
const std::string ProjectFileExtension( "kicad_pro" );
const std::string LegacyProjectFileExtension( "pro" );
const std::string ProjectLocalSettingsFileExtension( "kicad_prl" );
const std::string LegacySchematicFileExtension( "sch" );
const std::string KiCadSchematicFileExtension( "kicad_sch" );
const std::string NetlistFileExtension( "net" );

View File

@ -39,7 +39,7 @@
#include <cvpcb_association.h>
#include <cvpcb_mainframe.h>
#include <listboxes.h>
#include <settings/project_file.h>
#include <project/project_file.h>
#define QUOTE '\''

View File

@ -35,7 +35,7 @@
#include <cvpcb_mainframe.h>
#include <dialog_config_equfiles.h>
#include <settings/project_file.h>
#include <project/project_file.h>
#include <settings/settings_manager.h>
#include <wildcards_and_files_ext.h>

View File

@ -54,7 +54,7 @@
#include <connection_graph.h>
#include <tool/actions.h>
#include <tools/sch_editor_control.h>
#include <settings/project_file.h>
#include <project/project_file.h>
#include <settings/settings_manager.h>
#include <netlist.h>
#include <widgets/infobar.h>
@ -262,7 +262,7 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
return false;
wxFileName pro = fullFileName;
pro.SetExt( LegacyProjectFileExtension );
pro.SetExt( ProjectFileExtension );
bool is_new = !wxFileName::IsFileReadable( fullFileName );
@ -332,6 +332,8 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
Prj().SetElem( PROJECT::ELEM_SYMBOL_LIB_TABLE, NULL );
Prj().SchSymbolLibTable();
Schematic().SetProject( Prj() );
SetShutdownBlockReason( _( "Schematic file changes are unsaved" ) );
if( is_new )

View File

@ -43,7 +43,7 @@ SYMBOL_TREE_MODEL_ADAPTER::PTR SYMBOL_TREE_MODEL_ADAPTER::Create( EDA_BASE_FRAME
SYMBOL_TREE_MODEL_ADAPTER::SYMBOL_TREE_MODEL_ADAPTER( EDA_BASE_FRAME* aParent, LIB_TABLE* aLibs ) :
LIB_TREE_MODEL_ADAPTER( aParent ),
LIB_TREE_MODEL_ADAPTER( aParent, "pinned_symbol_libs" ),
m_libs( (SYMBOL_LIB_TABLE*) aLibs )
{}

View File

@ -39,7 +39,7 @@ LIB_TREE_MODEL_ADAPTER::PTR SYMBOL_TREE_SYNCHRONIZING_ADAPTER::Create( LIB_EDIT_
SYMBOL_TREE_SYNCHRONIZING_ADAPTER::SYMBOL_TREE_SYNCHRONIZING_ADAPTER( LIB_EDIT_FRAME* aParent,
LIB_MANAGER* aLibMgr ) :
LIB_TREE_MODEL_ADAPTER( aParent ),
LIB_TREE_MODEL_ADAPTER( aParent, "pinned_symbol_libs" ),
m_frame( aParent ),
m_libMgr( aLibMgr ),
m_lastSyncHash( -1 )

View File

@ -30,6 +30,9 @@
#include <config_params.h>
#include <board_stackup_manager/class_board_stackup.h>
#include <drc/drc_rule.h>
#include <settings/nested_settings.h>
#include <widgets/ui_common.h>
#include <zone_settings.h>
#define DEFAULT_SILK_LINE_WIDTH 0.12
@ -208,7 +211,7 @@ enum class VIATYPE : int;
* BOARD_DESIGN_SETTINGS
* contains design settings for a BOARD object.
*/
class BOARD_DESIGN_SETTINGS
class BOARD_DESIGN_SETTINGS : public NESTED_SETTINGS
{
public:
// Note: the first value in each dimensions list is the current netclass value
@ -217,7 +220,7 @@ public:
std::vector<DIFF_PAIR_DIMENSION> m_DiffPairDimensionsList;
// List of netclasses. There is always the default netclass.
NETCLASSES m_NetClasses;
//NETCLASSES m_NetClasses;
std::vector<DRC_SELECTOR*> m_DRCRuleSelectors;
std::vector<DRC_RULE*> m_DRCRules;
@ -242,6 +245,9 @@ public:
std::map< int, int > m_DRCSeverities; // Map from DRCErrorCode to SEVERITY
/// Excluded DRC items
std::set<wxString> m_DrcExclusions;
/** Option to handle filled polygons in zones:
* the "legacy" option is using thick outlines around filled polygons: give the best shape
* the "new" option is using only filled polygons (no outline: give the faster redraw time
@ -310,9 +316,7 @@ private:
int m_copperLayerCount; ///< Number of copper layers for this design
LSET m_enabledLayers; ///< Bit-mask for layer enabling
LSET m_visibleLayers; ///< Bit-mask for layer visibility
int m_visibleElements; ///< Bit-mask for element category visibility
int m_boardThickness; ///< Board thickness for 3D viewer
/// Current net class name used to display netclass info.
@ -325,8 +329,25 @@ private:
*/
BOARD_STACKUP m_stackup;
/// Net classes that are loaded from the board file before these were stored in the project
NETCLASSES m_internalNetClasses;
/// This will point to m_internalNetClasses until it is repointed to the project after load
NETCLASSES* m_netClasses;
/// The defualt settings that will be used for new zones
ZONE_SETTINGS m_defaultZoneSettings;
SEVERITY severityFromString( const wxString& aSeverity );
wxString severityToString( const SEVERITY& aSeverity );
public:
BOARD_DESIGN_SETTINGS();
BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath );
virtual ~BOARD_DESIGN_SETTINGS();
bool LoadFromFile( const std::string& aDirectory = "" ) override;
BOARD_STACKUP& GetStackupDescriptor() { return m_stackup; }
@ -337,13 +358,36 @@ public:
*/
bool Ignore( int aDRCErrorCode );
NETCLASSES& GetNetClasses() const
{
return *m_netClasses;
}
void SetNetClasses( NETCLASSES* aNetClasses )
{
if( aNetClasses )
m_netClasses = aNetClasses;
else
m_netClasses = &m_internalNetClasses;
}
ZONE_SETTINGS& GetDefaultZoneSettings()
{
return m_defaultZoneSettings;
}
void SetDefaultZoneSettings( const ZONE_SETTINGS& aSettings )
{
m_defaultZoneSettings = aSettings;
}
/**
* Function GetDefault
* @return the default netclass.
*/
inline NETCLASS* GetDefault() const
{
return m_NetClasses.GetDefaultPtr();
return GetNetClasses().GetDefaultPtr();
}
/**
@ -712,95 +756,6 @@ public:
*/
void SetCopperEdgeClearance( int aDistance );
/**
* Function GetVisibleLayers
* returns a bit-mask of all the layers that are visible
* @return int - the visible layers in bit-mapped form.
*/
inline LSET GetVisibleLayers() const
{
return m_visibleLayers;
}
/**
* Function SetVisibleAlls
* Set the bit-mask of all visible elements categories,
* including enabled layers
*/
void SetVisibleAlls();
/**
* Function SetVisibleLayers
* changes the bit-mask of visible layers
* @param aMask = The new bit-mask of visible layers
*/
inline void SetVisibleLayers( LSET aMask )
{
m_visibleLayers = aMask & m_enabledLayers;
}
/**
* Function IsLayerVisible
* tests whether a given layer is visible
* @param aLayerId = The layer to be tested
* @return bool - true if the layer is visible.
*/
inline bool IsLayerVisible( PCB_LAYER_ID aLayerId ) const
{
// If a layer is disabled, it is automatically invisible
return (m_visibleLayers & m_enabledLayers)[aLayerId];
}
/**
* Function SetLayerVisibility
* changes the visibility of a given layer
* @param aLayerId = The layer to be changed
* @param aNewState = The new visibility state of the layer
*/
void SetLayerVisibility( PCB_LAYER_ID aLayerId, bool aNewState );
/**
* Function GetVisibleElements
* returns a bit-mask of all the element categories that are visible
* @return int - the visible element categories in bit-mapped form.
*/
inline int GetVisibleElements() const
{
return m_visibleElements;
}
/**
* Function SetVisibleElements
* changes the bit-mask of visible element categories
* @param aMask = The new bit-mask of visible element categories
*/
inline void SetVisibleElements( int aMask )
{
m_visibleElements = aMask;
}
/**
* Function IsElementVisible
* tests whether a given element category is visible. Keep this as an
* inline function.
* @param aElementCategory is from the enum by the same name
* @return bool - true if the element is visible.
* @see enum GAL_LAYER_ID
*/
inline bool IsElementVisible( GAL_LAYER_ID aElementCategory ) const
{
return ( m_visibleElements & ( 1 << GAL_LAYER_INDEX( aElementCategory ) ) );
}
/**
* Function SetElementVisibility
* changes the visibility of an element category
* @param aElementCategory is from the enum by the same name
* @param aNewState = The new visibility state of the element category
* @see enum GAL_LAYER_ID
*/
void SetElementVisibility( GAL_LAYER_ID aElementCategory, bool aNewState );
/**
* Function GetEnabledLayers
* returns a bit-mask of all the layers that are enabled
@ -845,14 +800,6 @@ public:
*/
void SetCopperLayerCount( int aNewLayerCount );
/**
* Function AppendConfigs
* appends to @a aResult the configuration setting accessors which will later
* allow reading or writing of configuration file information directly into
* this object.
*/
void AppendConfigs( BOARD* aBoard, std::vector<PARAM_CFG*>* aResult );
inline int GetBoardThickness() const { return m_boardThickness; }
inline void SetBoardThickness( int aThickness ) { m_boardThickness = aThickness; }

View File

@ -44,6 +44,8 @@ public:
bool Migrate() override;
/// Only some of these settings are actually used for footprint editing
// TODO: factor out the relevant stuff so the whole BDS doesn't have to be here
BOARD_DESIGN_SETTINGS m_DesignSettings;
// Only the magneticPads element is used

View File

@ -218,6 +218,8 @@ enum GAL_LAYER_ID: int
/// Use this macro to convert a GAL layer to a 0-indexed offset from LAYER_VIAS
#define GAL_LAYER_INDEX( x ) ( x - GAL_LAYER_ID_START )
constexpr int GAL_LAYER_ID_COUNT = GAL_LAYER_ID_END - GAL_LAYER_ID_START;
inline GAL_LAYER_ID operator++( GAL_LAYER_ID& a )
{
a = GAL_LAYER_ID( int( a ) + 1 );
@ -402,6 +404,7 @@ public:
}
};
typedef std::bitset<GAL_LAYER_ID_COUNT> GAL_SET;
typedef std::bitset<PCB_LAYER_ID_COUNT> BASE_SET;

View File

@ -201,16 +201,6 @@ public:
*/
void SetParams( const NETCLASS& aDefaults );
/**
* Function Format
* outputs the net class to \a aFormatter in s-expression form.
*
* @param aFormatter The #OUTPUTFORMATTER object to write to.
* @param aNestLevel The indentation next level.
* @param aControlBits The control bit definition for object specific formatting.
* @throw IO_ERROR on write error.
*/
void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const;
#if defined(DEBUG)
void Show( int nestLevel, std::ostream& os ) const;

View File

@ -148,12 +148,10 @@ public:
void SetTitleBlock( const TITLE_BLOCK& aTitleBlock ) override;
/**
* Function GetDesignSettings
* returns the BOARD_DESIGN_SETTINGS for the BOARD owned by this frame.
* Returns the BOARD_DESIGN_SETTINGS for the open project
* Overloaded in FOOTPRINT_EDIT_FRAME.
*/
virtual BOARD_DESIGN_SETTINGS& GetDesignSettings() const;
virtual void SetDesignSettings( const BOARD_DESIGN_SETTINGS& aSettings );
/**
* Helper to retrieve the current color settings

View File

@ -48,6 +48,7 @@ class KIWAY;
class SYMBOL_LIB_TABLE;
class FILENAME_RESOLVER;
class PROJECT_FILE;
class PROJECT_LOCAL_SETTINGS;
#define VTBL_ENTRY virtual
@ -132,6 +133,12 @@ public:
return *m_projectFile;
}
VTBL_ENTRY PROJECT_LOCAL_SETTINGS& GetLocalSettings() const
{
wxASSERT( m_localSettings );
return *m_localSettings;
}
/**
* Function ConfigSave
* saves the current "project" parameters into the wxConfigBase* derivative.
@ -340,6 +347,15 @@ private:
m_projectFile = aFile;
}
/**
* Sets the local settings backing store. Should only be called by SETTINGS_MANAGER on load.
* @param aSettings is the local settings object (may or may not exist on disk at this point)
*/
VTBL_ENTRY void setLocalSettings( PROJECT_LOCAL_SETTINGS* aSettings )
{
m_localSettings = aSettings;
}
/**
* Function configCreate
* loads a *.pro file and returns a wxConfigBase.
@ -362,6 +378,9 @@ private:
/// Backing store for project data -- owned by SETTINGS_MANAGER
PROJECT_FILE* m_projectFile;
/// Backing store for project local settings -- owned by SETTINGS_MANAGER
PROJECT_LOCAL_SETTINGS* m_localSettings;
std::map<KIID, wxString> m_sheetNames;
std::map<wxString, wxString> m_textVars;

View File

@ -0,0 +1,46 @@
/*
* 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/>.
*/
#ifndef KICAD_NET_SETTINGS_H
#define KICAD_NET_SETTINGS_H
#include <netclass.h>
#include <settings/nested_settings.h>
/**
* NET_SETTINGS stores various net-related settings in a project context. These settings are
* accessible and editable from both the schematic and PCB editors.
*/
class NET_SETTINGS : public NESTED_SETTINGS
{
public:
NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath );
virtual ~NET_SETTINGS();
NETCLASSES m_NetClasses;
private:
NETCLASSPTR m_defaultClass;
// TODO: Add diff pairs, bus information, etc here.
};
#endif // KICAD_NET_SETTINGS_H

View File

@ -23,7 +23,9 @@
#include <common.h>
#include <settings/json_settings.h>
#include <settings/nested_settings.h>
class NET_SETTINGS;
/**
* For files like sheets and boards, a pair of that object KIID and display name
@ -31,6 +33,20 @@
*/
typedef std::pair<KIID, wxString> FILE_INFO_PAIR;
/**
* For storing PcbNew MRU paths of various types
*/
enum LAST_PATH_TYPE : unsigned int
{
LAST_PATH_NETLIST = 0,
LAST_PATH_STEP,
LAST_PATH_IDF,
LAST_PATH_VRML,
LAST_PATH_SPECCTRADSN,
LAST_PATH_GENCAD,
LAST_PATH_SIZE
};
/**
* PROJECT_FILE is the backing store for a PROJECT, in JSON format.
@ -47,9 +63,16 @@ public:
*/
PROJECT_FILE( const std::string& aFullPath );
virtual ~PROJECT_FILE() {}
virtual ~PROJECT_FILE() = default;
virtual bool MigrateFromLegacy( wxConfigBase* aLegacyFile ) override;
virtual bool MigrateFromLegacy( wxConfigBase* aCfg ) override;
bool SaveToFile( const std::string& aDirectory = "", bool aForce = false ) override;
void SetProject( PROJECT* aProject )
{
m_project = aProject;
}
std::vector<FILE_INFO_PAIR>& GetSheets()
{
@ -61,6 +84,11 @@ public:
return m_boards;
}
NET_SETTINGS& NetSettings()
{
return *m_NetSettings;
}
protected:
wxString getFileExt() const override;
@ -74,6 +102,9 @@ private:
/// A list of board files in this project
std::vector<FILE_INFO_PAIR> m_boards;
/// A link to the owning PROJECT
PROJECT* m_project;
/**
* Below are project-level settings that have not been moved to a dedicated file
*/
@ -95,6 +126,31 @@ public:
/// List of equivalence (equ) files used in the project
std::vector<wxString> m_EquivalenceFiles;
/**
* PcbNew params
*/
/// Page layout description file
wxString m_PageLayoutDescrFile;
/// MRU path storage
wxString m_PcbLastPath[LAST_PATH_SIZE];
/**
* Board design settings for this project's board. This will be initialized by PcbNew after
* loading a board so that BOARD_DESIGN_SETTINGS doesn't need to live in common for now.
* Owned by the BOARD; may be null if a board isn't loaded: be careful
*/
NESTED_SETTINGS* m_BoardSettings;
/**
* Net settings for this project (owned here)
* NOTE: If we go multi-board in the future, we have to decide whether to use a global
* NET_SETTINGS or have one per board. Right now I think global makes more sense (one set of
* schematics, one netlist partitioned into multiple boards)
*/
std::shared_ptr<NET_SETTINGS> m_NetSettings;
};
// Specializations to allow directly reading/writing FILE_INFO_PAIRs from JSON

View File

@ -0,0 +1,83 @@
/*
* 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/>.
*/
#ifndef KICAD_PROJECT_LOCAL_SETTINGS_H
#define KICAD_PROJECT_LOCAL_SETTINGS_H
#include <layers_id_colors_and_visibility.h>
#include <settings/json_settings.h>
#include <wildcards_and_files_ext.h>
class PROJECT;
/**
* The project local settings are things that are attached to a particular project, but also might
* be particular to a certain user editing that project, or change quickly, and therefore may not
* want to be checked in to version control or otherwise distributed with the main project.
*
* Examples include layer visibility, recently-used design entry settings, and so on.
*
* The backing store is a JSON file named <project>.kicad_prl
*
* This file doesn't need to exist for a project to be loaded. It will be created on-demand if
* any of the things stored here are modified by the user.
*/
class PROJECT_LOCAL_SETTINGS : public JSON_SETTINGS
{
public:
PROJECT_LOCAL_SETTINGS( const std::string& aFilename );
virtual ~PROJECT_LOCAL_SETTINGS() {}
bool MigrateFromLegacy( wxConfigBase* aLegacyConfig ) override;
bool SaveToFile( const std::string& aDirectory = "", bool aForce = false ) override;
void SetProject( PROJECT* aProject )
{
m_project = aProject;
}
protected:
wxString getFileExt() const override
{
return ProjectLocalSettingsFileExtension;
}
private:
/// A link to the owning project
PROJECT* m_project;
public:
/**
* Board settings
*/
/// The board layers that are turned on for viewing (@see PCB_LAYER_ID)
LSET m_VisibleLayers;
/// The GAL layers (aka items) that are turned on for viewing (@see GAL_LAYER_ID)
GAL_SET m_VisibleItems;
};
#endif

View File

@ -105,17 +105,15 @@ public:
m_map( aMap )
{}
void Load( JSON_SETTINGS* aSettings ) const override
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
{
if( m_readOnly )
return;
COLOR4D val = m_default;
if( OPT<COLOR4D> optval = aSettings->Get<COLOR4D>( m_path ) )
val = *optval;
( *m_map )[ m_key ] = val;
( *m_map )[ m_key ] = *optval;
else if( aResetIfMissing )
( *m_map )[ m_key ] = m_default;
}
void Store( JSON_SETTINGS* aSettings) const override

View File

@ -55,6 +55,8 @@ public:
std::string GetFilename() const { return m_filename; }
wxString GetFullFilename() const;
SETTINGS_LOC GetLocation() const { return m_location; }
void SetLegacyFilename( const std::string& aFilename ) { m_legacy_filename = aFilename; }
@ -81,8 +83,7 @@ public:
/**
* Calls Store() and then writes the contents of the JSON document to a file
* @param aDirectory is the directory to save to, including trailing separator
* @param aForce if true will always save, even if contents are not modified
* @return true if the file was saved
c * @return true if the file was saved
*/
virtual bool SaveToFile( const std::string& aDirectory = "", bool aForce = false );
@ -97,7 +98,7 @@ public:
* @param aPath is a string containing one or more keys separated by '.'
* @return a JSON object from within this one
*/
OPT<nlohmann::json> GetJson( std::string aPath ) const;
OPT<nlohmann::json> GetJson( const std::string& aPath ) const;
/**
* Fetches a value from within the JSON document.
@ -107,9 +108,9 @@ public:
* @return a value from within this document
*/
template<typename ValueType>
OPT<ValueType> Get( std::string aPath ) const
OPT<ValueType> Get( const std::string& aPath ) const
{
if( OPT<nlohmann::json> ret = GetJson( std::move( aPath ) ) )
if( OPT<nlohmann::json> ret = GetJson( aPath ) )
{
try
{
@ -131,9 +132,9 @@ public:
* @param aVal is the value to store
*/
template<typename ValueType>
void Set( std::string aPath, ValueType aVal )
void Set( const std::string& aPath, ValueType aVal )
{
( *this )[PointerFromString( std::move( aPath ) ) ] = aVal;
( *this )[PointerFromString( aPath ) ] = aVal;
}
/**
@ -253,6 +254,9 @@ protected:
/// Whether or not to delete legacy file after migration
bool m_deleteLegacyAfterMigration;
/// Whether or not to set parameters to their default value if missing from JSON on Load()
bool m_resetParamsIfMissing;
/// Version of this settings schema.
int m_schemaVersion;
@ -265,9 +269,9 @@ protected:
// Specializations to allow conversion between wxString and std::string via JSON_SETTINGS API
template<> OPT<wxString> JSON_SETTINGS::Get( std::string aPath ) const;
template<> OPT<wxString> JSON_SETTINGS::Get( const std::string& aPath ) const;
template<> void JSON_SETTINGS::Set<wxString>( std::string aPath, wxString aVal );
template<> void JSON_SETTINGS::Set<wxString>( const std::string& aPath, wxString aVal );
// Specializations to allow directly reading/writing wxStrings from JSON

View File

@ -49,7 +49,14 @@ public:
*/
bool SaveToFile( const std::string& aDirectory = "", bool aForce = false ) override;
private:
void SetParent( JSON_SETTINGS* aParent );
JSON_SETTINGS* GetParent()
{
return m_parent;
}
protected:
/// A pointer to the parent object to load and store from
JSON_SETTINGS* m_parent;

View File

@ -42,8 +42,9 @@ public:
/**
* Loads the value of this parameter from JSON to the underlying storage
* @param aSettings is the JSON_SETTINGS object to load from.
* @param aResetIfMissing if true will set the parameter to its default value if load fails
*/
virtual void Load( JSON_SETTINGS* aSettings ) const = 0;
virtual void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const = 0;
/**
* Stores the value of this parameter to the given JSON_SETTINGS object
@ -90,42 +91,42 @@ public:
PARAM( const std::string& aJsonPath, ValueType* aPtr, ValueType aDefault,
bool aReadOnly = false ) :
PARAM_BASE( aJsonPath, aReadOnly ),
m_ptr( aPtr ),
m_default( aDefault ),
m_min(),
m_max(),
m_use_minmax( false )
m_use_minmax( false ),
m_ptr( aPtr ),
m_default( aDefault )
{ }
PARAM( const std::string& aJsonPath, ValueType* aPtr, ValueType aDefault, ValueType aMin,
ValueType aMax, bool aReadOnly = false ) :
PARAM_BASE( aJsonPath, aReadOnly ),
m_ptr( aPtr ),
m_default( aDefault ),
m_min( aMin ),
m_max( aMax ),
m_use_minmax( true )
m_use_minmax( true ),
m_ptr( aPtr ),
m_default( aDefault )
{ }
void Load( JSON_SETTINGS* aSettings ) const override
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
{
if( m_readOnly )
return;
ValueType val = m_default;
if( OPT<ValueType> optval = aSettings->Get<ValueType>( m_path ) )
{
val = *optval;
ValueType val = *optval;
if( m_use_minmax )
{
if( m_max < val || val < m_min )
val = m_default;
}
}
*m_ptr = val;
*m_ptr = val;
}
else if( aResetIfMissing )
*m_ptr = m_default;
}
void Store( JSON_SETTINGS* aSettings ) const override
@ -157,13 +158,66 @@ public:
}
private:
ValueType* m_ptr;
ValueType m_default;
ValueType m_min;
ValueType m_max;
bool m_use_minmax;
protected:
ValueType* m_ptr;
ValueType m_default;
};
/**
* Stores a path as a string with directory separators normalized to unix-style
*/
class PARAM_PATH : public PARAM<wxString>
{
public:
PARAM_PATH( const std::string& aJsonPath, wxString* aPtr, wxString aDefault,
bool aReadOnly = false ) :
PARAM( aJsonPath, aPtr, aDefault, aReadOnly )
{ }
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
{
if( m_readOnly )
return;
PARAM::Load( aSettings, aResetIfMissing );
*m_ptr = fromFileFormat( *m_ptr );
}
void Store( JSON_SETTINGS* aSettings ) const override
{
aSettings->Set<wxString>( m_path, toFileFormat( *m_ptr ) );
}
bool MatchesFile( JSON_SETTINGS* aSettings ) const override
{
if( OPT<wxString> optval = aSettings->Get<wxString>( m_path ) )
return fromFileFormat( *optval ) == *m_ptr;
return false;
}
private:
wxString toFileFormat( const wxString& aString ) const
{
wxString ret = aString;
ret.Replace( wxT( "\\" ), wxT( "/" ) );
return ret;
}
wxString fromFileFormat( const wxString& aString ) const
{
wxString ret = aString;
#ifdef __WINDOWS__
ret.Replace( wxT( "/" ), wxT( "\\" ) );
#endif
return ret;
}
};
/**
* Like a normal param, but with custom getter and setter functions
@ -182,28 +236,28 @@ public:
m_setter( aSetter )
{ }
void Load( JSON_SETTINGS* aSettings ) const override
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
{
if( m_readOnly )
return;
ValueType val = m_default;
if( std::is_same<ValueType, nlohmann::json>::value )
{
if( OPT<nlohmann::json> optval = aSettings->GetJson( m_path ) )
val = *optval;
m_setter( *optval );
else
m_setter( m_default );
}
else
{
if( OPT<ValueType> optval = aSettings->Get<ValueType>( m_path ) )
val = *optval;
m_setter( *optval );
else
m_setter( m_default );
}
m_setter( val );
}
void Store( JSON_SETTINGS* aSettings) const override
void Store( JSON_SETTINGS* aSettings ) const override
{
try
{
@ -287,7 +341,7 @@ public:
m_scale( aScale )
{ }
void Load( JSON_SETTINGS* aSettings ) const override
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
{
if( m_readOnly )
return;
@ -296,6 +350,8 @@ public:
if( OPT<double> optval = aSettings->Get<double>( m_path ) )
dval = *optval;
else if( !aResetIfMissing )
return;
ValueType val = KiROUND<ValueType>( dval / m_scale );
@ -363,25 +419,25 @@ public:
m_default( aDefault )
{ }
void Load( JSON_SETTINGS* aSettings ) const override
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
{
if( m_readOnly )
return;
std::vector<Type> val = m_default;
if( OPT<nlohmann::json> js = aSettings->GetJson( m_path ) )
{
std::vector<Type> val;
if( js->is_array() )
{
val.clear();
for( const auto& el : js->items() )
val.push_back( el.value().get<Type>() );
}
}
*m_ptr = val;
*m_ptr = val;
}
else if( aResetIfMissing )
*m_ptr = m_default;
}
void Store( JSON_SETTINGS* aSettings) const override
@ -445,12 +501,12 @@ public:
PARAM_LIST( aJsonPath, aPtr, aDefault, aReadOnly )
{ }
void Load( JSON_SETTINGS* aSettings ) const override
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
{
if( m_readOnly )
return;
PARAM_LIST::Load( aSettings );
PARAM_LIST::Load( aSettings, aResetIfMissing );
for( size_t i = 0; i < m_ptr->size(); i++ )
( *m_ptr )[i] = fromFileFormat( ( *m_ptr )[i] );
@ -526,7 +582,7 @@ public:
m_default( aDefault )
{ }
void Load( JSON_SETTINGS* aSettings ) const override
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override
{
if( m_readOnly )
return;

View File

@ -61,7 +61,7 @@ public:
* If the given settings object is registered, save it to disk and unregister it
* @param aSettings is the object to release
*/
void FlushAndRelease( JSON_SETTINGS* aSettings );
void FlushAndRelease( JSON_SETTINGS* aSettings, bool aSave = true );
/**
* Returns a handle to the a given settings by type
@ -184,16 +184,18 @@ public:
/**
* Loads a project or sets up a new project with a specified path
* @param aFullPath is the full path to the project
* @param aSetActive if true will set the loaded project as the active project
* @return true if the PROJECT_FILE was successfully loaded from disk
*/
bool LoadProject( const wxString& aFullPath );
bool LoadProject( const wxString& aFullPath, bool aSetActive = true );
/**
* Saves, unloads and unregisters the given PROJECT
* @param aProject is the project object to unload
* @param aSave if true will save the project before unloading
* @return true if the PROJECT file was successfully saved
*/
bool UnloadProject( PROJECT& aProject );
bool UnloadProject( PROJECT* aProject, bool aSave = true );
/**
* A helper while we are not MDI-capable -- return the one and only project
@ -202,16 +204,23 @@ public:
PROJECT& Prj() const;
/**
* Saves the one and only project
* TODO: Update for MDI
* @return true if save was successful
* Retrieves a loaded project by name
* @param aFullPath is the full path including name and extension to the project file
* @return a pointer to the project if loaded, or nullptr
*/
bool SaveProject();
PROJECT* GetProject( const wxString& aFullPath ) const;
/**
* @return the path to the settings folder for the loaded project
* Saves a loaded project.
* @param aFullPath is the project name to save. If empty, will save the first loaded project.
* @return true if save was successful
*/
wxString GetProjectSettingsPath() const;
bool SaveProject( const wxString& aFullPath = wxEmptyString );
/**
* @return the path to the backups folder for the loaded project
*/
wxString GetProjectBackupsPath() const;
/**
* Checks if a given path is probably a valid KiCad configuration directory.
@ -300,11 +309,12 @@ private:
bool loadProjectFile( PROJECT& aProject );
/**
* Saves, unloads and unregisters the given PROJECT_FILE
* Optionally saves, and then unloads and unregisters the given PROJECT_FILE
* @param aProject is the project object to unload the file for
* @param aSave if true will save the project file before unloading
* @return true if the PROJECT file was successfully saved
*/
bool unloadProjectFile( PROJECT& aProject );
bool unloadProjectFile( PROJECT* aProject, bool aSave );
private:

View File

@ -116,6 +116,7 @@ extern const std::string SchematicBackupFileExtension;
extern const std::string VrmlFileExtension;
extern const std::string ProjectFileExtension;
extern const std::string LegacyProjectFileExtension;
extern const std::string ProjectLocalSettingsFileExtension;
extern const std::string LegacySchematicFileExtension;
extern const std::string KiCadSchematicFileExtension;
extern const std::string NetlistFileExtension;

View File

@ -56,14 +56,6 @@
#define SEP() wxFileName::GetPathSeparator()
// Not really useful, provided to save/restore params in project config file,
// (Add them in s_KicadManagerParams if any)
// Used also to create new .pro files from the kicad.pro template file
// for new projects
#define GeneralGroupName wxT( "/general" )
std::vector<PARAM_CFG*> s_KicadManagerParams;
// Menubar and toolbar event table
BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME )

View File

@ -448,7 +448,6 @@ if( KICAD_SCRIPTING ) # Generate pcbnew.py and pcbnew_wrap.cxx using swig
DEPENDS swig/pcb_target.i
DEPENDS swig/pcb_plot_params.i
DEPENDS swig/footprint.i
DEPENDS swig/netclass.i
DEPENDS swig/netinfo.i
DEPENDS swig/pad.i
DEPENDS swig/pcb_text.i
@ -463,6 +462,7 @@ if( KICAD_SCRIPTING ) # Generate pcbnew.py and pcbnew_wrap.cxx using swig
DEPENDS ${CMAKE_SOURCE_DIR}/common/swig/kicad.i
DEPENDS ${CMAKE_SOURCE_DIR}/common/swig/wx.i
DEPENDS ${CMAKE_SOURCE_DIR}/common/swig/ki_exception.i
DEPENDS ${CMAKE_SOURCE_DIR}/common/swig/netclass.i
DEPENDS ${CMAKE_SOURCE_DIR}/scripting/kicadplugins.i
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/docstrings

View File

@ -757,7 +757,7 @@ void ALTIUM_PCB::ParseClasses6Data(
if( elem.kind == ALTIUM_CLASS_KIND::NET_CLASS )
{
const NETCLASSPTR& netclass = std::make_shared<NETCLASS>( elem.name );
designSettings.m_NetClasses.Add( netclass );
designSettings.GetNetClasses().Add( netclass );
for( const auto& name : elem.names )
{

File diff suppressed because it is too large Load Diff

View File

@ -68,26 +68,26 @@ public:
Remove( aItem );
delete aItem;
}
/**
* @brief Fetch the zone settings for this container
*/
const ZONE_SETTINGS& GetZoneSettings() const
{
return m_zoneSettings;
}
/**
* @brief Set the zone settings for this container
* @param aSettings new Zone settings for this container
*/
void SetZoneSettings( const ZONE_SETTINGS& aSettings )
{
m_zoneSettings = aSettings;
}
private:
ZONE_SETTINGS m_zoneSettings;
/**
* @brief Fetch the zone settings for this container
*/
virtual const ZONE_SETTINGS& GetZoneSettings() const
{
return m_zoneSettings;
}
/**
* @brief Set the zone settings for this container
* @param aSettings new Zone settings for this container
*/
virtual void SetZoneSettings( const ZONE_SETTINGS& aSettings )
{
m_zoneSettings = aSettings;
}
private:
ZONE_SETTINGS m_zoneSettings;
};
#endif /* BOARD_ITEM_CONTAINER_H */

View File

@ -41,6 +41,10 @@
#include <connectivity/connectivity_data.h>
#include <pgm_base.h>
#include <pcbnew_settings.h>
#include <project.h>
#include <project/net_settings.h>
#include <project/project_file.h>
#include <project/project_local_settings.h>
#include <ratsnest/ratsnest_data.h>
#include <ratsnest/ratsnest_viewitem.h>
@ -81,23 +85,19 @@ DELETED_BOARD_ITEM* g_DeletedItem = nullptr;
*/
wxPoint BOARD_ITEM::ZeroOffset( 0, 0 );
// Dummy settings used to initialize the board.
// This is needed because some APIs that make use of BOARD without the context of a frame or
// application, and so the BOARD needs to store a valid pointer to a PCBNEW_SETTINGS even if
// one hasn't been provided by the application.
static PCBNEW_SETTINGS dummyGeneralSettings;
BOARD::BOARD() :
BOARD_ITEM_CONTAINER( (BOARD_ITEM*) NULL, PCB_T ),
m_paper( PAGE_INFO::A4 ),
m_project( nullptr ),
m_designSettings( new BOARD_DESIGN_SETTINGS( nullptr, "board.design_settings" ) ),
m_NetInfo( this ),
m_project( nullptr )
m_LegacyDesignSettingsLoaded( false ),
m_LegacyNetclassesLoaded( false )
{
// we have not loaded a board yet, assume latest until then.
m_fileFormatVersionAtLoad = LEGACY_BOARD_FILE_VERSION;
m_generalSettings = &dummyGeneralSettings;
m_CurrentZoneContour = NULL; // This ZONE_CONTAINER handle the
// zone contour currently in progress
@ -113,19 +113,25 @@ BOARD::BOARD() :
m_Layer[layer].m_type = LT_UNDEFINED;
}
BOARD_DESIGN_SETTINGS& bds = GetDesignSettings();
// Initialize default netclass.
NETCLASS* defaultClass = m_designSettings.GetDefault();
NETCLASS* defaultClass = bds.GetDefault();
defaultClass->SetDescription( _( "This is the default net class." ) );
m_designSettings.SetCurrentNetClass( defaultClass->GetName() );
bds.SetCurrentNetClass( defaultClass->GetName() );
// Set sensible initial values for custom track width & via size
m_designSettings.UseCustomTrackViaSize( false );
m_designSettings.SetCustomTrackWidth( m_designSettings.GetCurrentTrackWidth() );
m_designSettings.SetCustomViaSize( m_designSettings.GetCurrentViaSize() );
m_designSettings.SetCustomViaDrill( m_designSettings.GetCurrentViaDrill() );
bds.UseCustomTrackViaSize( false );
bds.SetCustomTrackWidth( bds.GetCurrentTrackWidth() );
bds.SetCustomViaSize( bds.GetCurrentViaSize() );
bds.SetCustomViaDrill( bds.GetCurrentViaDrill() );
// Initialize ratsnest
m_connectivity.reset( new CONNECTIVITY_DATA() );
// Set flag bits on these that will only be cleared if these are loaded from a legacy file
m_LegacyVisibleLayers.reset().set( Rescue );
m_LegacyVisibleItems.reset().set( GAL_LAYER_INDEX( GAL_LAYER_ID_BITMASK_END ) );
}
@ -170,6 +176,54 @@ void BOARD::BuildConnectivity()
}
void BOARD::SetProject( PROJECT* aProject )
{
m_project = aProject;
if( aProject )
{
PROJECT_FILE& project = aProject->GetProjectFile();
// Link the design settings object to the project file
project.m_BoardSettings = &GetDesignSettings();
// Set parent, which also will load the values from JSON stored in the project
project.m_BoardSettings->SetParent( &project );
// The netclasses pointer will be pointing to the internal netclasses list at this point. If
// it has anything other than the default net, this means we loaded some netclasses from a
// board saved in legacy format where the netclass info is included. Move this info to the
// netclasses stored in the project.
NETCLASSES& local = GetDesignSettings().GetNetClasses();
if( m_LegacyNetclassesLoaded )
project.NetSettings().m_NetClasses = local;
GetDesignSettings().SetNetClasses( &project.NetSettings().m_NetClasses );
}
}
void BOARD::ClearProject()
{
if( !m_project )
return;
PROJECT_FILE& project = m_project->GetProjectFile();
// Owned by the BOARD
if( project.m_BoardSettings )
{
project.ReleaseNestedSettings( project.m_BoardSettings );
project.m_BoardSettings = nullptr;
}
GetDesignSettings().SetParent( nullptr );
m_project = nullptr;
}
const wxPoint BOARD::GetPosition() const
{
return ZeroOffset;
@ -392,50 +446,56 @@ LAYER_T LAYER::ParseType( const char* aType )
int BOARD::GetCopperLayerCount() const
{
return m_designSettings.GetCopperLayerCount();
return GetDesignSettings().GetCopperLayerCount();
}
void BOARD::SetCopperLayerCount( int aCount )
{
m_designSettings.SetCopperLayerCount( aCount );
GetDesignSettings().SetCopperLayerCount( aCount );
}
LSET BOARD::GetEnabledLayers() const
{
return m_designSettings.GetEnabledLayers();
return GetDesignSettings().GetEnabledLayers();
}
bool BOARD::IsLayerVisible( PCB_LAYER_ID aLayer ) const
{
// If there is no project, assume layer is visible always
return GetDesignSettings().IsLayerEnabled( aLayer )
&& ( !m_project || m_project->GetLocalSettings().m_VisibleLayers[aLayer] );
}
LSET BOARD::GetVisibleLayers() const
{
return m_designSettings.GetVisibleLayers();
return m_project ? m_project->GetLocalSettings().m_VisibleLayers : LSET::AllLayersMask();
}
void BOARD::SetEnabledLayers( LSET aLayerSet )
{
m_designSettings.SetEnabledLayers( aLayerSet );
GetDesignSettings().SetEnabledLayers( aLayerSet );
}
void BOARD::SetVisibleLayers( LSET aLayerSet )
{
m_designSettings.SetVisibleLayers( aLayerSet );
if( m_project )
m_project->GetLocalSettings().m_VisibleLayers = aLayerSet;
}
void BOARD::SetVisibleElements( int aMask )
void BOARD::SetVisibleElements( const GAL_SET& aSet )
{
// Call SetElementVisibility for each item
// to ensure specific calculations that can be needed by some items,
// just changing the visibility flags could be not sufficient.
for( GAL_LAYER_ID ii = GAL_LAYER_ID_START; ii < GAL_LAYER_ID_BITMASK_END; ++ii )
{
int item_mask = 1 << GAL_LAYER_INDEX( ii );
SetElementVisibility( ii, aMask & item_mask );
}
for( size_t i = 0; i < aSet.size(); i++ )
SetElementVisibility( GAL_LAYER_ID_START + static_cast<int>( i ), aSet[i] );
}
@ -450,21 +510,22 @@ void BOARD::SetVisibleAlls()
}
int BOARD::GetVisibleElements() const
GAL_SET BOARD::GetVisibleElements() const
{
return m_designSettings.GetVisibleElements();
return m_project ? m_project->GetLocalSettings().m_VisibleItems : GAL_SET().set();
}
bool BOARD::IsElementVisible( GAL_LAYER_ID aLayer ) const
{
return m_designSettings.IsElementVisible( aLayer );
return !m_project || m_project->GetLocalSettings().m_VisibleItems[aLayer - GAL_LAYER_ID_START];
}
void BOARD::SetElementVisibility( GAL_LAYER_ID aLayer, bool isEnabled )
{
m_designSettings.SetElementVisibility( aLayer, isEnabled );
if( m_project )
m_project->GetLocalSettings().m_VisibleItems.set( aLayer - GAL_LAYER_ID_START, isEnabled );
switch( aLayer )
{
@ -1216,6 +1277,86 @@ int BOARD::SortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount )
}
void BOARD::SynchronizeNetsAndNetClasses()
{
NETCLASSES& netClasses = GetDesignSettings().GetNetClasses();
NETCLASSPTR defaultNetClass = netClasses.GetDefault();
// set all NETs to the default NETCLASS, then later override some
// as we go through the NETCLASSes.
for( NETINFO_LIST::iterator net( m_NetInfo.begin() ), netEnd( m_NetInfo.end() );
net != netEnd; ++net )
{
net->SetClass( defaultNetClass );
}
// Add netclass name and pointer to nets. If a net is in more than one netclass,
// set the net's name and pointer to only the first netclass. Subsequent
// and therefore bogus netclass memberships will be deleted in logic below this loop.
for( NETCLASSES::iterator clazz = netClasses.begin(); clazz != netClasses.end(); ++clazz )
{
NETCLASSPTR netclass = clazz->second;
for( NETCLASS::const_iterator member = netclass->begin(); member != netclass->end(); ++member )
{
const wxString& netname = *member;
// although this overall function seems to be adequately fast,
// FindNet( wxString ) uses now a fast binary search and is fast
// event for large net lists
NETINFO_ITEM* net = FindNet( netname );
if( net && net->GetClassName() == NETCLASS::Default )
{
net->SetClass( netclass );
}
}
}
// Finally, make sure that every NET is in a NETCLASS, even if that
// means the Default NETCLASS. And make sure that all NETCLASSes do not
// contain netnames that do not exist, by deleting all netnames from
// every netclass and re-adding them.
for( NETCLASSES::iterator clazz = netClasses.begin(); clazz != netClasses.end(); ++clazz )
{
NETCLASSPTR netclass = clazz->second;
netclass->Clear();
}
defaultNetClass->Clear();
for( NETINFO_LIST::iterator net( m_NetInfo.begin() ), netEnd( m_NetInfo.end() );
net != netEnd; ++net )
{
const wxString& classname = net->GetClassName();
// because of the std:map<> this should be fast, and because of
// prior logic, netclass should not be NULL.
NETCLASSPTR netclass = netClasses.Find( classname );
wxASSERT( netclass );
netclass->Add( net->GetNetname() );
}
BOARD_DESIGN_SETTINGS& bds = GetDesignSettings();
// Set initial values for custom track width & via size to match the default netclass settings
bds.UseCustomTrackViaSize( false );
bds.SetCustomTrackWidth( defaultNetClass->GetTrackWidth() );
bds.SetCustomViaSize( defaultNetClass->GetViaDiameter() );
bds.SetCustomViaDrill( defaultNetClass->GetViaDrill() );
bds.SetCustomDiffPairWidth( defaultNetClass->GetDiffPairWidth() );
bds.SetCustomDiffPairGap( defaultNetClass->GetDiffPairGap() );
bds.SetCustomDiffPairViaGap( defaultNetClass->GetDiffPairViaGap() );
InvokeListeners( &BOARD_LISTENER::OnBoardNetSettingsChanged, *this );
}
int BOARD::SetAreasNetCodesFromNetNames()
{
int error_count = 0;

View File

@ -42,7 +42,6 @@
class PCB_BASE_FRAME;
class PCB_EDIT_FRAME;
class PCBNEW_SETTINGS;
class PICKED_ITEMS_LIST;
class BOARD;
class ZONE_CONTAINER;
@ -211,13 +210,24 @@ private:
std::shared_ptr<CONNECTIVITY_DATA> m_connectivity;
BOARD_DESIGN_SETTINGS m_designSettings;
PCBNEW_SETTINGS* m_generalSettings; // reference only; I have no ownership
PAGE_INFO m_paper;
TITLE_BLOCK m_titles; // text in lower right of screen and plots
PCB_PLOT_PARAMS m_plotOptions;
PROJECT* m_project; // project this board is a part of
/**
* All of the board design settings are stored as a JSON object inside the project file. The
* object itself is located here because the alternative is to require a valid project be
* passed in when constructing a BOARD, since things in the BOARD constructor rely on access
* to the BOARD_DESIGN_SETTINGS object.
*
* A reference to this object is set up in the PROJECT_FILE for the PROJECT this board is
* part of, so that the JSON load/store operations work. This link is established when
* boards are loaded from disk.
*/
std::unique_ptr<BOARD_DESIGN_SETTINGS> m_designSettings;
NETINFO_LIST m_NetInfo; // net info list (name, design constraints ..
PROJECT* m_project; // project this board is a part of (if any)
std::vector<BOARD_LISTENER*> m_listeners;
@ -282,6 +292,16 @@ public:
/// zone contour currently in progress
ZONE_CONTAINER* m_CurrentZoneContour;
/// Visibility settings stored in board prior to 6.0, only used for loading legacy files
LSET m_LegacyVisibleLayers;
GAL_SET m_LegacyVisibleItems;
/// True if the legacy board design settings were loaded from a file
bool m_LegacyDesignSettingsLoaded;
/// True if netclasses were loaded from the file
bool m_LegacyNetclassesLoaded;
BOARD();
~BOARD();
@ -354,7 +374,15 @@ public:
void DeleteZONEOutlines();
PROJECT* GetProject() const { return m_project; }
void SetProject( PROJECT* aProject ) { m_project = aProject; }
/**
* Links a board to a given project. Should be called immediately after loading board in
* order for everything to work
* @param aProject is a loaded project to link to
*/
void SetProject( PROJECT* aProject );
void ClearProject();
/**
* Function ResetNetHighLight
@ -434,7 +462,7 @@ public:
*/
bool IsLayerEnabled( PCB_LAYER_ID aLayer ) const
{
return m_designSettings.IsLayerEnabled( aLayer );
return GetDesignSettings().IsLayerEnabled( aLayer );
}
/**
@ -444,10 +472,7 @@ public:
* @param aLayer = The layer to be tested
* @return bool - true if the layer is visible.
*/
bool IsLayerVisible( PCB_LAYER_ID aLayer ) const
{
return m_designSettings.IsLayerVisible( aLayer );
}
bool IsLayerVisible( PCB_LAYER_ID aLayer ) const;
/**
* Function GetVisibleLayers
@ -469,13 +494,11 @@ public:
// are not stored in the bitmap.
/**
* Function GetVisibleElements
* is a proxy function that calls the correspondent function in m_BoardSettings
* returns a bit-mask of all the element categories that are visible
* @return int - the visible element bitmap or-ed from enum GAL_LAYER_ID
* Returns a set of all the element categories that are visible
* @return the set of visible GAL layers
* @see enum GAL_LAYER_ID
*/
int GetVisibleElements() const;
GAL_SET GetVisibleElements() const;
/**
* Function SetVisibleElements
@ -484,7 +507,7 @@ public:
* @param aMask = The new bit-mask of visible element bitmap or-ed from enum GAL_LAYER_ID
* @see enum GAL_LAYER_ID
*/
void SetVisibleElements( int aMask );
void SetVisibleElements( const GAL_SET& aMask );
/**
* Function SetVisibleAlls
@ -528,16 +551,22 @@ public:
BOARD_DESIGN_SETTINGS& GetDesignSettings() const
{
// remove const-ness with cast. TODO(snh): Make GetDesignSettings const
return const_cast<BOARD_DESIGN_SETTINGS&>( m_designSettings );
// NOTE(JE) If we want this to be const, it's going to have to involve making BOARD and
// everything else that relies on BOARD_DESIGN_SETTINGS aware of the PROJECT so that it
// can be retrieved from there. This will also currently require constructing BOARD with
// a valid PROJECT passed in to the ctor.
return const_cast<BOARD_DESIGN_SETTINGS&>( *m_designSettings.get() );
}
/**
* Function SetDesignSettings
* @param aDesignSettings the new BOARD_DESIGN_SETTINGS to use
*/
void SetDesignSettings( const BOARD_DESIGN_SETTINGS& aDesignSettings )
const ZONE_SETTINGS& GetZoneSettings() const override
{
m_designSettings = aDesignSettings;
return GetDesignSettings().GetDefaultZoneSettings();
}
void SetZoneSettings( const ZONE_SETTINGS& aSettings ) override
{
GetDesignSettings().SetDefaultZoneSettings( aSettings );
}
const PAGE_INFO& GetPageSettings() const { return m_paper; }
@ -551,13 +580,6 @@ public:
wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
const PCBNEW_SETTINGS& GeneralSettings() const { return *m_generalSettings; }
void SetGeneralSettings( PCBNEW_SETTINGS* aSettings )
{
m_generalSettings = aSettings;
}
/**
* Function GetBoardPolygonOutlines
* Extracts the board outlines and build a closed polygon

View File

@ -487,37 +487,6 @@ void D_PAD::MirrorXPrimitives( int aX )
}
void D_PAD::AppendConfigs( std::vector<PARAM_CFG*>* aResult )
{
// Parameters stored in config are only significant parameters
// for a template.
// So not all parameters are stored, just few.
aResult->push_back( new PARAM_CFG_INT_WITH_SCALE( wxT( "PadDrill" ),
&m_Drill.x,
Millimeter2iu( 0.6 ),
Millimeter2iu( 0.1 ), Millimeter2iu( 10.0 ),
NULL, MM_PER_IU ) );
aResult->push_back( new PARAM_CFG_INT_WITH_SCALE( wxT( "PadDrillOvalY" ),
&m_Drill.y,
Millimeter2iu( 0.6 ),
Millimeter2iu( 0.1 ), Millimeter2iu( 10.0 ),
NULL, MM_PER_IU ) );
aResult->push_back( new PARAM_CFG_INT_WITH_SCALE( wxT( "PadSizeH" ),
&m_Size.x,
Millimeter2iu( 1.4 ),
Millimeter2iu( 0.1 ), Millimeter2iu( 20.0 ),
NULL, MM_PER_IU ) );
aResult->push_back( new PARAM_CFG_INT_WITH_SCALE( wxT( "PadSizeV" ),
&m_Size.y,
Millimeter2iu( 1.4 ),
Millimeter2iu( 0.1 ), Millimeter2iu( 20.0 ),
NULL, MM_PER_IU ) );
}
// Returns the position of the pad.
wxPoint D_PAD::ShapePos() const
{

View File

@ -551,14 +551,6 @@ public:
*/
wxString ShowPadAttr() const;
/**
* Function AppendConfigs
* appends to @a aResult the configuration setting accessors which will later
* allow reading or writing of configuration file information directly into
* this object.
*/
void AppendConfigs( std::vector<PARAM_CFG*>* aResult );
EDA_ITEM* Clone() const override;
/**

View File

@ -24,18 +24,24 @@
#include <panel_setup_tracks_and_vias.h>
#include <panel_setup_mask_and_paste.h>
#include <../board_stackup_manager/panel_board_stackup.h>
#include <confirm.h>
#include <kiface_i.h>
#include <drc/drc.h>
#include <drc/drc_item.h>
#include <dialog_import_settings.h>
#include <io_mgr.h>
#include <panel_setup_severities.h>
#include <panel_text_variables.h>
#include <project.h>
#include <project/project_file.h>
#include <settings/settings_manager.h>
#include <wildcards_and_files_ext.h>
#include "dialog_board_setup.h"
#include "panel_setup_rules.h"
DIALOG_BOARD_SETUP::DIALOG_BOARD_SETUP( PCB_EDIT_FRAME* aFrame ) :
PAGED_DIALOG( aFrame, _( "Board Setup" ), _( "Import Settings from Another Project..." ) ),
PAGED_DIALOG( aFrame, _( "Board Setup" ), _( "Import Settings from Another Board..." ) ),
m_frame( aFrame )
{
m_layers = new PANEL_SETUP_LAYERS( this, aFrame );
@ -127,30 +133,59 @@ void DIALOG_BOARD_SETUP::OnAuxiliaryAction( wxCommandEvent& event )
if( importDlg.ShowModal() == wxID_CANCEL )
return;
wxConfigBase* cfg = new wxFileConfig( wxEmptyString, wxEmptyString, importDlg.GetFilePath() );
wxFileName boardFn( importDlg.GetFilePath() );
wxFileName projectFn( boardFn );
// We do not want expansion of env var values when reading our project config file
cfg->SetExpandEnvVars( false );
cfg->SetPath( wxCONFIG_PATH_SEPARATOR );
projectFn.SetExt( ProjectFileExtension );
BOARD* dummyBoard = new BOARD();
std::vector<PARAM_CFG*> designSettingsConfig;
if( !m_frame->GetSettingsManager()->LoadProject( projectFn.GetFullPath(), false ) )
{
wxString msg = wxString::Format( _( "Error importing settings from borad:\n"
"Associated project file %s could not be loaded" ),
projectFn.GetFullPath() );
DisplayErrorMessage( this, msg );
dummyBoard->GetDesignSettings().AppendConfigs( dummyBoard, &designSettingsConfig );
wxConfigLoadParams( cfg, designSettingsConfig, GROUP_PCB );
return;
}
PROJECT* otherPrj = m_frame->GetSettingsManager()->GetProject( projectFn.GetFullPath() );
PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::KICAD_SEXP ) );
BOARD* otherBoard = new BOARD();
try
{
otherBoard = pi->Load( boardFn.GetFullPath(), nullptr, nullptr );
}
catch( const IO_ERROR& ioe )
{
if( ioe.Problem() != wxT( "CANCEL" ) )
{
wxString msg =
wxString::Format( _( "Error loading board file:\n%s" ), boardFn.GetFullPath() );
DisplayErrorMessage( this, msg, ioe.What() );
}
m_frame->GetSettingsManager()->UnloadProject( otherPrj, false );
return;
}
otherBoard->SetProject( otherPrj );
if( importDlg.m_LayersOpt->GetValue() )
m_layers->ImportSettingsFrom( dummyBoard );
m_layers->ImportSettingsFrom( otherBoard );
if( importDlg.m_TextAndGraphicsOpt->GetValue() )
m_textAndGraphics->ImportSettingsFrom( dummyBoard );
m_textAndGraphics->ImportSettingsFrom( otherBoard );
if( importDlg.m_ConstraintsOpt->GetValue() )
m_constraints->ImportSettingsFrom( dummyBoard );
m_constraints->ImportSettingsFrom( otherBoard );
if( importDlg.m_NetclassesOpt->GetValue() )
m_netclasses->ImportSettingsFrom( dummyBoard );
m_netclasses->ImportSettingsFrom( otherBoard );
if( importDlg.m_TracksAndViasOpt->GetValue() )
m_tracksAndVias->ImportSettingsFrom( dummyBoard );
m_tracksAndVias->ImportSettingsFrom( otherBoard );
if( importDlg.m_MaskAndPasteOpt->GetValue() )
m_maskAndPaste->ImportSettingsFrom( dummyBoard );
m_maskAndPaste->ImportSettingsFrom( otherBoard );
// If layers options are imported, import also the stackup
// layers options and stackup are linked, so they cannot be imported
@ -159,12 +194,16 @@ void DIALOG_BOARD_SETUP::OnAuxiliaryAction( wxCommandEvent& event )
// Note also currently only the list of enabled layers can be imported, because
// we import settings from a .pro project file, not the settings inside
// a board, and info only living in the board is not imported.
// TODO: Add import of physical settings now that we are actually loading the board here
if( importDlg.m_LayersOpt->GetValue() )
m_physicalStackup->ImportSettingsFrom( dummyBoard );
m_physicalStackup->ImportSettingsFrom( otherBoard );
if( importDlg.m_SeveritiesOpt->GetValue() )
m_severities->ImportSettingsFrom( dummyBoard->GetDesignSettings().m_DRCSeverities );
m_severities->ImportSettingsFrom( otherBoard->GetDesignSettings().m_DRCSeverities );
delete dummyBoard;
delete cfg;
otherBoard->ClearProject();
m_frame->GetSettingsManager()->UnloadProject( otherPrj, false );
delete otherBoard;
}

View File

@ -30,6 +30,7 @@
#include <dialog_export_idf_base.h>
#include <pcb_edit_frame.h>
#include <pcbnew_settings.h>
#include <project/project_file.h> // LAST_PATH_TYPE
#include <confirm.h>

View File

@ -33,6 +33,7 @@
#include "class_board.h"
#include "dialog_export_step_base.h"
#include <pcbnew_settings.h>
#include <project/project_file.h> // LAST_PATH_TYPE
#include <widgets/text_ctrl_eval.h>
#include <wx_html_report_panel.h>

View File

@ -35,6 +35,7 @@
#include <pcb_edit_frame.h>
#include <pcbnew_settings.h>
#include <pcbnew.h>
#include <project/project_file.h> // LAST_PATH_TYPE
/* the dialog to create VRML files, derived from DIALOG_EXPORT_3DFILE_BASE,

View File

@ -170,7 +170,7 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::buildFilterLists()
// Populate the netclass filter list with netclass names
wxArrayString netclassNames;
NETCLASSES& netclasses = m_brd->GetDesignSettings().m_NetClasses;
NETCLASSES& netclasses = m_brd->GetDesignSettings().GetNetClasses();
netclassNames.push_back( netclasses.GetDefaultPtr()->GetName() );
@ -200,7 +200,7 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::buildNetclassesGrid()
m_netclassGrid->SetCellValue( 0, GRID_uVIASIZE, _( "uVia Size" ) );
m_netclassGrid->SetCellValue( 0, GRID_uVIADRILL, _( "uVia Drill" ) );
NETCLASSES& netclasses = m_brd->GetDesignSettings().m_NetClasses;
NETCLASSES& netclasses = m_brd->GetDesignSettings().GetNetClasses();
NETCLASS* defaultNetclass = m_brd->GetDesignSettings().GetDefault();
m_netclassGrid->AppendRows( netclasses.GetCount() + 1 );

View File

@ -59,7 +59,7 @@ void DIALOG_IMPORT_SETTINGS::OnBrowseClicked( wxCommandEvent& event )
fn.SetExt( LegacyProjectFileExtension );
wxFileDialog dlg( this, _( "Import Settings From" ), fn.GetPath(), fn.GetFullName(),
ProjectFileWildcard(), wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR );
PcbFileWildcard(), wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR );
if( dlg.ShowModal() == wxID_OK )
m_filePathCtrl->SetValue( dlg.GetPath() );

View File

@ -41,6 +41,7 @@
#include <wildcards_and_files_ext.h>
#include <netlist_reader/pcb_netlist.h>
#include <netlist_reader/board_netlist_updater.h>
#include <project/project_file.h> // LAST_PATH_TYPE
#include <dialog_netlist.h>

View File

@ -24,6 +24,7 @@
#include <fctsys.h>
#include <widgets/paged_dialog.h>
#include <footprint_edit_frame.h>
#include <footprint_editor_settings.h>
#include <widgets/wx_grid.h>
#include <grid_tricks.h>
@ -361,7 +362,8 @@ bool PANEL_MODEDIT_DEFAULTS::TransferDataFromWindow()
m_brdSettings.m_DefaultFPTextItems.emplace_back( text, visible, layer );
}
m_frame->SetDesignSettings( m_brdSettings );
if( FOOTPRINT_EDITOR_SETTINGS* cfg = m_frame->GetSettings() )
cfg->m_DesignSettings = m_brdSettings;
return true;
}

View File

@ -152,8 +152,8 @@ static void netclassToGridRow( EDA_UNITS aUnits, wxGrid* aGrid, int aRow, const
bool PANEL_SETUP_NETCLASSES::TransferDataToWindow()
{
NETCLASSES& netclasses = m_BrdSettings->m_NetClasses;
NETCLASSPTR netclass = netclasses.GetDefault();
NETCLASSES& netclasses = m_BrdSettings->GetNetClasses();
NETCLASSPTR netclass = netclasses.GetDefault();
if( m_netclassGrid->GetNumberRows() )
m_netclassGrid->DeleteRows( 0, m_netclassGrid->GetNumberRows() );
@ -250,7 +250,7 @@ bool PANEL_SETUP_NETCLASSES::TransferDataFromWindow()
if( !validateData() )
return false;
NETCLASSES& netclasses = m_BrdSettings->m_NetClasses;
NETCLASSES& netclasses = m_BrdSettings->GetNetClasses();
// Remove all netclasses from board. We'll copy new list after
netclasses.Clear();
@ -263,7 +263,7 @@ bool PANEL_SETUP_NETCLASSES::TransferDataFromWindow()
{
NETCLASSPTR nc = std::make_shared<NETCLASS>( m_netclassGrid->GetCellValue( row, GRID_NAME ) );
if( m_BrdSettings->m_NetClasses.Add( nc ) )
if( netclasses.Add( nc ) )
gridRowToNetclass( m_Frame->GetUserUnits(), m_netclassGrid, row, nc );
}

View File

@ -39,7 +39,7 @@ bool DRC_NETCLASS_TESTER::RunDRC( EDA_UNITS aUnits, BOARD& aBoard )
m_board = &aBoard;
bool success = true;
NETCLASSES& netclasses = m_board->GetDesignSettings().m_NetClasses;
NETCLASSES& netclasses = m_board->GetDesignSettings().GetNetClasses();
success &= checkNetClass( netclasses.GetDefault() );

View File

@ -132,7 +132,7 @@ void DRC_RULES_PARSER::Parse( std::vector<DRC_SELECTOR*>& aSelectors,
DRC_SELECTOR* DRC_RULES_PARSER::parseDRC_SELECTOR( wxString* aRuleName )
{
NETCLASSES& netclasses = m_board->GetDesignSettings().m_NetClasses;
NETCLASSES& netclasses = m_board->GetDesignSettings().GetNetClasses();
DRC_SELECTOR* selector = new DRC_SELECTOR();
T token;

View File

@ -45,6 +45,7 @@
#include <pcbnew.h>
#include <pcbnew_settings.h>
#include <pgm_base.h>
#include <project/project_file.h> // LAST_PATH_TYPE
#include <trigo.h>
static bool CreateHeaderInfoData( FILE* aFile, PCB_EDIT_FRAME* frame );

View File

@ -452,7 +452,7 @@ void GERBER_JOBFILE_WRITER::addJSONDesignRules()
bool hasInnerLayers = m_pcb->GetCopperLayerCount() > 2;
// Search a smaller clearance in other net classes, if any.
for( const std::pair<const wxString, NETCLASSPTR>& entry : dsnSettings.m_NetClasses )
for( const std::pair<const wxString, NETCLASSPTR>& entry : dsnSettings.GetNetClasses() )
minclearanceOuter = std::min( minclearanceOuter, entry.second->GetClearance() );
// job file knows different clearance types.

View File

@ -52,6 +52,8 @@
#include <wx/wupdlock.h>
#include <settings/settings_manager.h>
#include <project/project_file.h>
#include <project/project_local_settings.h>
//#define USE_INSTRUMENTATION 1
@ -305,14 +307,19 @@ bool PCB_EDIT_FRAME::Files_io_from_id( int id )
return false;
}
if( !Clear_Pcb( false ) )
return false;
GetSettingsManager()->SaveProject( GetSettingsManager()->Prj().GetProjectFullName() );
GetBoard()->ClearProject();
wxFileName fn( wxStandardPaths::Get().GetDocumentsDir(), wxT( "noname" ),
LegacyProjectFileExtension );
ProjectFileExtension );
GetSettingsManager()->LoadProject( fn.GetFullPath() );
LoadProjectSettings();
if( !Clear_Pcb( false ) )
return false;
onBoardLoaded();
OnModify();
@ -478,7 +485,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
ReleaseFile();
wxFileName pro = fullFileName;
pro.SetExt( LegacyProjectFileExtension );
pro.SetExt( ProjectFileExtension );
bool is_new = !wxFileName::IsFileReadable( fullFileName );
@ -494,7 +501,11 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
wxWindowUpdateLocker no_update( m_Layers ); // Avoid flicker when rebuilding m_Layers
Clear_Pcb( false ); // pass false since we prompted above for a modified board
// Unlink the old project if needed
GetBoard()->ClearProject();
// No save prompt (we already prompted above), and only reset to a new blank board if new
Clear_Pcb( false, !is_new );
IO_MGR::PCB_FILE_T pluginType = plugin_type( fullFileName, aCtl );
@ -502,8 +513,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
if( !converted )
{
// PROJECT::SetProjectFullName() is an impactful function. It should only be
// called under carefully considered circumstances.
// Loading a project should only be done under carefully considered circumstances.
// The calling code should know not to ask me here to change projects unless
// it knows what consequences that will have on other KIFACEs running and using
@ -560,40 +570,30 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
DisplayErrorMessage( this, msg, ioe.What() );
}
// We didn't create a new blank board above, so do that now
Clear_Pcb( false );
return false;
}
BOARD_DESIGN_SETTINGS& bds = loadedBoard->m_designSettings;
SetBoard( loadedBoard );
if( bds.m_CopperEdgeClearance == Millimeter2iu( LEGACY_COPPEREDGECLEARANCE ) )
// On save; design settings will be removed from the board
if( loadedBoard->m_LegacyDesignSettingsLoaded )
loadedBoard->SetModified();
// Move legacy view settings to local project settings
if( !loadedBoard->m_LegacyVisibleLayers.test( Rescue ) )
{
// 5.1 boards stored some settings in the config so as not to bump the file version.
// These will have been loaded into the config-initialized board, so we copy them
// from there.
BOARD_DESIGN_SETTINGS& configBds = GetBoard()->GetDesignSettings();
bds.m_DRCSeverities = configBds.m_DRCSeverities;
bds.m_HoleToHoleMin = configBds.m_HoleToHoleMin;
bds.m_LineThickness[LAYER_CLASS_OTHERS] = configBds.m_LineThickness[LAYER_CLASS_OTHERS];
bds.m_TextSize[LAYER_CLASS_OTHERS] = configBds.m_TextSize[LAYER_CLASS_OTHERS];
bds.m_TextThickness[LAYER_CLASS_OTHERS] = configBds.m_TextThickness[LAYER_CLASS_OTHERS];
std::copy( configBds.m_TextItalic, configBds.m_TextItalic + 4, bds.m_TextItalic );
std::copy( configBds.m_TextUpright, configBds.m_TextUpright + 4, bds.m_TextUpright );
bds.m_DiffPairDimensionsList = configBds.m_DiffPairDimensionsList;
bds.m_CopperEdgeClearance = configBds.m_CopperEdgeClearance;
// Before we had a copper edge clearance setting, the edge line widths could be used
// as a kludge to control them. So if there's no setting then infer it from the
// edge widths.
if( bds.m_CopperEdgeClearance == Millimeter2iu( LEGACY_COPPEREDGECLEARANCE ) )
bds.SetCopperEdgeClearance( inferLegacyEdgeClearance( loadedBoard ) );
Prj().GetLocalSettings().m_VisibleLayers = loadedBoard->m_LegacyVisibleLayers;
loadedBoard->SetModified();
}
// We store the severities in the config to keep board-file changes to a minimum
BOARD_DESIGN_SETTINGS& configBds = GetBoard()->GetDesignSettings();
bds.m_DRCSeverities = configBds.m_DRCSeverities;
SetBoard( loadedBoard );
if( !loadedBoard->m_LegacyVisibleItems.test( GAL_LAYER_INDEX( GAL_LAYER_ID_BITMASK_END ) ) )
{
Prj().GetLocalSettings().m_VisibleItems = loadedBoard->m_LegacyVisibleItems;
loadedBoard->SetModified();
}
// we should not ask PLUGINs to do these items:
loadedBoard->BuildListOfNets();
@ -723,6 +723,21 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF
return false;
}
// TODO: this will break if we ever go multi-board
wxFileName projectFile( pcbFileName );
projectFile.SetExt( ProjectFileExtension );
if( !projectFile.FileExists() )
{
// If this is a new board, project filename won't be set yet
if( projectFile.GetFullPath() != Prj().GetProjectFullName() )
{
GetBoard()->ClearProject();
GetSettingsManager()->LoadProject( projectFile.GetFullPath() );
GetBoard()->SetProject( &Prj() );
}
}
wxString backupFileName;
if( aCreateBackupFile )
@ -743,6 +758,8 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool aCreateBackupF
// edited via the DRC dialog as well as the Board Setup dialog), DRC exclusions, etc.
SaveProjectSettings();
GetSettingsManager()->SaveProject();
ClearMsgPanel();
wxString upperTxt;

View File

@ -401,12 +401,6 @@ BOARD_DESIGN_SETTINGS& FOOTPRINT_EDIT_FRAME::GetDesignSettings() const
}
void FOOTPRINT_EDIT_FRAME::SetDesignSettings( const BOARD_DESIGN_SETTINGS& aSettings )
{
GetBoard()->SetDesignSettings( aSettings );
}
const PCB_PLOT_PARAMS& FOOTPRINT_EDIT_FRAME::GetPlotSettings() const
{
wxFAIL_MSG( "Plotting not supported in Footprint Editor" );

View File

@ -74,7 +74,6 @@ public:
FOOTPRINT_EDITOR_SETTINGS* GetSettings();
BOARD_DESIGN_SETTINGS& GetDesignSettings() const override;
void SetDesignSettings( const BOARD_DESIGN_SETTINGS& aSettings ) override;
const PCB_PLOT_PARAMS& GetPlotSettings() const override;
void SetPlotSettings( const PCB_PLOT_PARAMS& aSettings ) override;

View File

@ -39,7 +39,7 @@ const int fpEditSchemaVersion = 1;
FOOTPRINT_EDITOR_SETTINGS::FOOTPRINT_EDITOR_SETTINGS() :
APP_SETTINGS_BASE( "fpedit", fpEditSchemaVersion ),
m_DesignSettings(),
m_DesignSettings( nullptr, "fpedit.settings" ),
m_MagneticItems(),
m_Display(),
m_UserGrid(),

View File

@ -34,7 +34,7 @@ FP_TREE_MODEL_ADAPTER::PTR FP_TREE_MODEL_ADAPTER::Create( EDA_BASE_FRAME* aParen
FP_TREE_MODEL_ADAPTER::FP_TREE_MODEL_ADAPTER( EDA_BASE_FRAME* aParent, LIB_TABLE* aLibs ) :
LIB_TREE_MODEL_ADAPTER( aParent ),
LIB_TREE_MODEL_ADAPTER( aParent, "pinned_footprint_libs" ),
m_libs( (FP_LIB_TABLE*) aLibs )
{}

View File

@ -29,6 +29,9 @@
#include <fctsys.h>
#include <confirm.h>
#include <pcb_edit_frame.h>
#include <project.h>
#include <project/net_settings.h>
#include <project/project_file.h>
#include <class_board.h>
@ -55,18 +58,11 @@ bool PCB_EDIT_FRAME::Clear_Pcb( bool aQuery, bool aFinal )
GetScreen()->ClearUndoRedoList();
GetScreen()->ClrModify();
// Items visibility flags will be set because a new board will be created.
// Grid and ratsnest can be left to their previous state
bool showGrid = IsElementVisible( LAYER_GRID );
bool showRats = GetDisplayOptions().m_ShowGlobalRatsnest;
if( !aFinal )
{
// delete the old BOARD and create a new BOARD so that the default
// layer names are put into the BOARD.
SetBoard( new BOARD() );
SetElementVisibility( LAYER_GRID, showGrid );
SetElementVisibility( LAYER_RATSNEST, showRats );
// clear filename, to avoid overwriting an old file
GetBoard()->SetFileName( wxEmptyString );
@ -118,10 +114,6 @@ bool FOOTPRINT_EDIT_FRAME::Clear_Pcb( bool aQuery )
BOARD* board = new BOARD;
// Transfer current design settings
if( GetBoard() )
board->SetDesignSettings( GetBoard()->GetDesignSettings() );
board->SynchronizeNetsAndNetClasses();
SetBoard( board );

View File

@ -472,8 +472,6 @@ void PCB_IO::formatLayer( const BOARD_ITEM* aItem ) const
void PCB_IO::formatSetup( BOARD* aBoard, int aNestLevel ) const
{
const BOARD_DESIGN_SETTINGS& dsnSettings = aBoard->GetDesignSettings();
// Setup
m_out->Print( aNestLevel, "(setup\n" );
@ -483,104 +481,7 @@ void PCB_IO::formatSetup( BOARD* aBoard, int aNestLevel ) const
if( aBoard->GetDesignSettings().m_HasStackup )
stackup.FormatBoardStackup( m_out,aBoard, aNestLevel+1 );
// Save current default track width, for compatibility with older Pcbnew version;
m_out->Print( aNestLevel+1, "(last_trace_width %s)\n",
FormatInternalUnits( dsnSettings.GetCurrentTrackWidth() ).c_str() );
// Save custom track widths list (the first is not saved here: it's the netclass value)
for( unsigned ii = 1; ii < dsnSettings.m_TrackWidthList.size(); ii++ )
{
m_out->Print( aNestLevel+1, "(user_trace_width %s)\n",
FormatInternalUnits( dsnSettings.m_TrackWidthList[ii] ).c_str() );
}
m_out->Print( aNestLevel+1, "(trace_clearance %s)\n",
FormatInternalUnits( dsnSettings.GetDefault()->GetClearance() ).c_str() );
// ZONE_SETTINGS
m_out->Print( aNestLevel+1, "(zone_clearance %s)\n",
FormatInternalUnits( aBoard->GetZoneSettings().m_ZoneClearance ).c_str() );
m_out->Print( aNestLevel+1, "(zone_45_only %s)\n",
aBoard->GetZoneSettings().m_Zone_45_Only ? "yes" : "no" );
m_out->Print( aNestLevel+1, "(trace_min %s)\n",
FormatInternalUnits( dsnSettings.m_TrackMinWidth ).c_str() );
m_out->Print( aNestLevel+1, "(clearance_min %s)\n",
FormatInternalUnits( dsnSettings.m_MinClearance ).c_str() );
m_out->Print( aNestLevel+1, "(via_min_annulus %s)\n",
FormatInternalUnits( dsnSettings.m_ViasMinAnnulus ).c_str() );
m_out->Print( aNestLevel+1, "(via_min_size %s)\n",
FormatInternalUnits( dsnSettings.m_ViasMinSize ).c_str() );
m_out->Print( aNestLevel+1, "(through_hole_min %s)\n",
FormatInternalUnits( dsnSettings.m_MinThroughDrill ).c_str() );
m_out->Print( aNestLevel+1, "(hole_to_hole_min %s)\n",
FormatInternalUnits( dsnSettings.m_HoleToHoleMin ).c_str() );
// Save current default via size, for compatibility with older Pcbnew version;
m_out->Print( aNestLevel+1, "(via_size %s)\n",
FormatInternalUnits( dsnSettings.GetDefault()->GetViaDiameter() ).c_str() );
m_out->Print( aNestLevel+1, "(via_drill %s)\n",
FormatInternalUnits( dsnSettings.GetDefault()->GetViaDrill() ).c_str() );
// Save custom via dimensions list (the first is not saved here: it's the netclass value)
for( unsigned ii = 1; ii < dsnSettings.m_ViasDimensionsList.size(); ii++ )
m_out->Print( aNestLevel+1, "(user_via %s %s)\n",
FormatInternalUnits( dsnSettings.m_ViasDimensionsList[ii].m_Diameter ).c_str(),
FormatInternalUnits( dsnSettings.m_ViasDimensionsList[ii].m_Drill ).c_str() );
// Save custom diff-pair dimensions (the first is not saved here: it's the netclass value)
for( unsigned ii = 1; ii < dsnSettings.m_DiffPairDimensionsList.size(); ii++ )
{
m_out->Print( aNestLevel+1, "(user_diff_pair %s %s %s)\n",
FormatInternalUnits( dsnSettings.m_DiffPairDimensionsList[ii].m_Width ).c_str(),
FormatInternalUnits( dsnSettings.m_DiffPairDimensionsList[ii].m_Gap ).c_str(),
FormatInternalUnits( dsnSettings.m_DiffPairDimensionsList[ii].m_ViaGap ).c_str() );
}
// for old versions compatibility:
if( dsnSettings.m_BlindBuriedViaAllowed )
m_out->Print( aNestLevel+1, "(blind_buried_vias_allowed yes)\n" );
m_out->Print( aNestLevel+1, "(uvia_size %s)\n",
FormatInternalUnits( dsnSettings.GetDefault()->GetuViaDiameter() ).c_str() );
m_out->Print( aNestLevel+1, "(uvia_drill %s)\n",
FormatInternalUnits( dsnSettings.GetDefault()->GetuViaDrill() ).c_str() );
m_out->Print( aNestLevel+1, "(uvias_allowed %s)\n",
( dsnSettings.m_MicroViasAllowed ) ? "yes" : "no" );
m_out->Print( aNestLevel+1, "(uvia_min_size %s)\n",
FormatInternalUnits( dsnSettings.m_MicroViasMinSize ).c_str() );
m_out->Print( aNestLevel+1, "(uvia_min_drill %s)\n",
FormatInternalUnits( dsnSettings.m_MicroViasMinDrill ).c_str() );
m_out->Print( aNestLevel+1, "(max_error %s)\n",
FormatInternalUnits( dsnSettings.m_MaxError ).c_str() );
// Store this option only if it is not the legacy option:
if( dsnSettings.m_ZoneUseNoOutlineInFill )
m_out->Print( aNestLevel+1, "(filled_areas_thickness no)\n" );
formatDefaults( dsnSettings, aNestLevel+1 );
m_out->Print( aNestLevel+1, "(pad_size %s %s)\n",
FormatInternalUnits( dsnSettings.m_Pad_Master.GetSize().x ).c_str(),
FormatInternalUnits( dsnSettings.m_Pad_Master.GetSize().y ).c_str() );
m_out->Print( aNestLevel+1, "(pad_drill %s)\n",
FormatInternalUnits( dsnSettings.m_Pad_Master.GetDrillSize().x ).c_str() );
m_out->Print( aNestLevel+1, "(pad_to_mask_clearance %s)\n",
FormatInternalUnits( dsnSettings.m_SolderMaskMargin ).c_str() );
if( dsnSettings.m_SolderMaskMinWidth )
m_out->Print( aNestLevel+1, "(solder_mask_min_width %s)\n",
FormatInternalUnits( dsnSettings.m_SolderMaskMinWidth ).c_str() );
if( dsnSettings.m_SolderPasteMargin != 0 )
m_out->Print( aNestLevel+1, "(pad_to_paste_clearance %s)\n",
FormatInternalUnits( dsnSettings.m_SolderPasteMargin ).c_str() );
if( dsnSettings.m_SolderPasteMarginRatio != 0 )
m_out->Print( aNestLevel+1, "(pad_to_paste_clearance_ratio %s)\n",
Double2Str( dsnSettings.m_SolderPasteMarginRatio ).c_str() );
BOARD_DESIGN_SETTINGS& dsnSettings = aBoard->GetDesignSettings();
if( dsnSettings.m_AuxOrigin != wxPoint( 0, 0 ) )
m_out->Print( aNestLevel+1, "(aux_axis_origin %s %s)\n",
@ -592,71 +493,12 @@ void PCB_IO::formatSetup( BOARD* aBoard, int aNestLevel ) const
FormatInternalUnits( dsnSettings.m_GridOrigin.x ).c_str(),
FormatInternalUnits( dsnSettings.m_GridOrigin.y ).c_str() );
m_out->Print( aNestLevel+1, "(visible_elements %X)\n",
dsnSettings.GetVisibleElements() );
aBoard->GetPlotOptions().Format( m_out, aNestLevel+1 );
m_out->Print( aNestLevel, ")\n\n" );
}
void PCB_IO::formatDefaults( const BOARD_DESIGN_SETTINGS& aSettings, int aNestLevel ) const
{
m_out->Print( aNestLevel, "(defaults\n" );
m_out->Print( aNestLevel+1, "(edge_clearance %s)\n",
FormatInternalUnits( aSettings.m_CopperEdgeClearance ).c_str() );
m_out->Print( aNestLevel+1, "(edge_cuts_line_width %s)\n",
FormatInternalUnits( aSettings.m_LineThickness[ LAYER_CLASS_EDGES ] ).c_str() );
m_out->Print( aNestLevel+1, "(courtyard_line_width %s)\n",
FormatInternalUnits( aSettings.m_LineThickness[ LAYER_CLASS_COURTYARD ] ).c_str() );
m_out->Print( aNestLevel+1, "(copper_line_width %s)\n",
FormatInternalUnits( aSettings.m_LineThickness[ LAYER_CLASS_COPPER ] ).c_str() );
m_out->Print( aNestLevel+1, "(copper_text_dims (size %s %s) (thickness %s)%s%s)\n",
FormatInternalUnits( aSettings.m_TextSize[ LAYER_CLASS_COPPER ].x ).c_str(),
FormatInternalUnits( aSettings.m_TextSize[ LAYER_CLASS_COPPER ].y ).c_str(),
FormatInternalUnits( aSettings.m_TextThickness[ LAYER_CLASS_COPPER ] ).c_str(),
aSettings.m_TextItalic[ LAYER_CLASS_COPPER ] ? " italic" : "",
aSettings.m_TextUpright[ LAYER_CLASS_COPPER ] ? " keep_upright" : "" );
m_out->Print( aNestLevel+1, "(silk_line_width %s)\n",
FormatInternalUnits( aSettings.m_LineThickness[ LAYER_CLASS_SILK ] ).c_str() );
m_out->Print( aNestLevel+1, "(silk_text_dims (size %s %s) (thickness %s)%s%s)\n",
FormatInternalUnits( aSettings.m_TextSize[ LAYER_CLASS_SILK ].x ).c_str(),
FormatInternalUnits( aSettings.m_TextSize[ LAYER_CLASS_SILK ].y ).c_str(),
FormatInternalUnits( aSettings.m_TextThickness[ LAYER_CLASS_SILK ] ).c_str(),
aSettings.m_TextItalic[ LAYER_CLASS_SILK ] ? " italic" : "",
aSettings.m_TextUpright[ LAYER_CLASS_SILK ] ? " keep_upright" : "" );
m_out->Print( aNestLevel+1, "(fab_layers_line_width %s)\n",
FormatInternalUnits( aSettings.m_LineThickness[ LAYER_CLASS_FAB ] ).c_str() );
m_out->Print( aNestLevel+1, "(fab_layers_text_dims (size %s %s) (thickness %s)%s%s)\n",
FormatInternalUnits( aSettings.m_TextSize[ LAYER_CLASS_FAB ].x ).c_str(),
FormatInternalUnits( aSettings.m_TextSize[ LAYER_CLASS_FAB ].y ).c_str(),
FormatInternalUnits( aSettings.m_TextThickness[ LAYER_CLASS_FAB ] ).c_str(),
aSettings.m_TextItalic[ LAYER_CLASS_OTHERS ] ? " italic" : "",
aSettings.m_TextUpright[ LAYER_CLASS_OTHERS ] ? " keep_upright" : "" );
m_out->Print( aNestLevel+1, "(other_layers_line_width %s)\n",
FormatInternalUnits( aSettings.m_LineThickness[ LAYER_CLASS_OTHERS ] ).c_str() );
m_out->Print( aNestLevel+1, "(other_layers_text_dims (size %s %s) (thickness %s)%s%s)\n",
FormatInternalUnits( aSettings.m_TextSize[ LAYER_CLASS_OTHERS ].x ).c_str(),
FormatInternalUnits( aSettings.m_TextSize[ LAYER_CLASS_OTHERS ].y ).c_str(),
FormatInternalUnits( aSettings.m_TextThickness[ LAYER_CLASS_OTHERS ] ).c_str(),
aSettings.m_TextItalic[ LAYER_CLASS_OTHERS ] ? " italic" : "",
aSettings.m_TextUpright[ LAYER_CLASS_OTHERS ] ? " keep_upright" : "" );
m_out->Print( aNestLevel+1, "(dimension_units %d)\n", aSettings.m_DimensionUnits );
m_out->Print( aNestLevel+1, "(dimension_precision %d)\n", aSettings.m_DimensionPrecision );
m_out->Print( aNestLevel, ")\n" );
}
void PCB_IO::formatGeneral( BOARD* aBoard, int aNestLevel ) const
{
const BOARD_DESIGN_SETTINGS& dsnSettings = aBoard->GetDesignSettings();
@ -683,7 +525,6 @@ void PCB_IO::formatBoardLayers( BOARD* aBoard, int aNestLevel ) const
m_out->Print( aNestLevel, "(layers\n" );
// Save only the used copper layers from front to back.
LSET visible_layers = aBoard->GetVisibleLayers();
for( LSEQ cu = aBoard->GetEnabledLayers().CuStack(); cu; ++cu )
{
@ -693,9 +534,6 @@ void PCB_IO::formatBoardLayers( BOARD* aBoard, int aNestLevel ) const
m_out->Quotew( aBoard->GetLayerName( layer ) ).c_str(),
LAYER::ShowType( aBoard->GetLayerType( layer ) ) );
if( !visible_layers[layer] )
m_out->Print( 0, " hide" );
m_out->Print( 0, ")\n" );
}
@ -730,9 +568,6 @@ void PCB_IO::formatBoardLayers( BOARD* aBoard, int aNestLevel ) const
m_out->Print( aNestLevel+1, "(%d %s user", layer,
m_out->Quotew( aBoard->GetLayerName( layer ) ).c_str() );
if( !visible_layers[layer] )
m_out->Print( 0, " hide" );
m_out->Print( 0, ")\n" );
}
@ -742,7 +577,6 @@ void PCB_IO::formatBoardLayers( BOARD* aBoard, int aNestLevel ) const
void PCB_IO::formatNetInformation( BOARD* aBoard, int aNestLevel ) const
{
const BOARD_DESIGN_SETTINGS& dsnSettings = aBoard->GetDesignSettings();
for( NETINFO_ITEM* net : *m_mapping )
{
m_out->Print( aNestLevel, "(net %d %s)\n",
@ -751,19 +585,6 @@ void PCB_IO::formatNetInformation( BOARD* aBoard, int aNestLevel ) const
}
m_out->Print( 0, "\n" );
// Save the default net class first.
NETCLASS defaultNC = *dsnSettings.GetDefault();
filterNetClass( *aBoard, defaultNC ); // Remove empty nets (from a copy of a netclass)
defaultNC.Format( m_out, aNestLevel, m_ctl );
// Save the rest of the net classes alphabetically.
for( const auto& it : dsnSettings.m_NetClasses )
{
NETCLASS netclass = *it.second;
filterNetClass( *aBoard, netclass ); // Remove empty nets (from a copy of a netclass)
netclass.Format( m_out, aNestLevel, m_ctl );
}
}

View File

@ -70,7 +70,8 @@ class TEXTE_PCB;
//#define SEXPR_BOARD_FILE_VERSION 20200512 // page -> paper
//#define SEXPR_BOARD_FILE_VERSION 20200518 // save hole_to_hole_min
//#define SEXPR_BOARD_FILE_VERSION 20200614 // Add support for fp_rects and gr_rects
#define SEXPR_BOARD_FILE_VERSION 20200625 // Multilayer zones, zone names, island controls
//#define SEXPR_BOARD_FILE_VERSION 20200625 // Multilayer zones, zone names, island controls
#define SEXPR_BOARD_FILE_VERSION 20200628 // remove visibility settings
#define CTL_STD_LAYER_NAMES (1 << 0) ///< Use English Standard layer names
#define CTL_OMIT_NETS (1 << 1) ///< Omit pads net names (useless in library)
@ -216,9 +217,6 @@ protected:
/// formats the board setup information
void formatSetup( BOARD* aBoard, int aNestLevel = 0 ) const;
/// formats the defaults subsection of the board setup
void formatDefaults( const BOARD_DESIGN_SETTINGS& aSettings, int aNestLevel ) const;
/// formats the General section of the file
void formatGeneral( BOARD* aBoard, int aNestLevel = 0 ) const;

View File

@ -832,13 +832,13 @@ void LEGACY_PLUGIN::loadSHEET()
void LEGACY_PLUGIN::loadSETUP()
{
NETCLASS* netclass_default = m_board->GetDesignSettings().GetDefault();
// TODO Orson: is it really necessary to first operate on a copy and then apply it?
// would not it be better to use reference here and apply all the changes instantly?
BOARD_DESIGN_SETTINGS bds = m_board->GetDesignSettings();
ZONE_SETTINGS zs = m_board->GetZoneSettings();
char* line;
char* saveptr;
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
ZONE_SETTINGS zs = m_board->GetZoneSettings();
NETCLASS* netclass_default = bds.GetDefault();
char* line;
char* saveptr;
m_board->m_LegacyDesignSettingsLoaded = true;
while( ( line = READLINE( m_reader ) ) != NULL )
{
@ -1118,12 +1118,17 @@ void LEGACY_PLUGIN::loadSETUP()
else if( TESTLINE( "VisibleElements" ) )
{
int visibleElements = hexParse( line + SZ( "VisibleElements" ) );
bds.SetVisibleElements( visibleElements );
GAL_SET visibles;
for( size_t i = 0; i < visibles.size(); i++ )
visibles.set( i, visibleElements & ( 1u << i ) );
m_board->SetVisibleElements( visibles );
}
else if( TESTLINE( "$EndSETUP" ) )
{
m_board->SetDesignSettings( bds );
m_board->SetZoneSettings( zs );
// Very old *.brd file does not have NETCLASSes
@ -2399,7 +2404,7 @@ void LEGACY_PLUGIN::loadNETCLASS()
else if( TESTLINE( "$EndNCLASS" ) )
{
if( !m_board->GetDesignSettings().m_NetClasses.Add( nc ) )
if( !m_board->GetDesignSettings().GetNetClasses().Add( nc ) )
{
// Must have been a name conflict, this is a bad board file.
// User may have done a hand edit to the file.

View File

@ -56,7 +56,7 @@ NETINFO_ITEM::NETINFO_ITEM( BOARD* aParent, const wxString& aNetName, int aNetCo
m_parent = aParent;
if( aParent )
m_NetClass = aParent->GetDesignSettings().m_NetClasses.GetDefault();
m_NetClass = aParent->GetDesignSettings().GetNetClasses().GetDefault();
else
m_NetClass = std::make_shared<NETCLASS>( "<invalid>" );
}
@ -71,7 +71,7 @@ NETINFO_ITEM::~NETINFO_ITEM()
void NETINFO_ITEM::SetClass( const NETCLASSPTR& aNetClass )
{
wxCHECK( m_parent, /* void */ );
m_NetClass = aNetClass ? aNetClass : m_parent->GetDesignSettings().m_NetClasses.GetDefault();
m_NetClass = aNetClass ? aNetClass : m_parent->GetDesignSettings().GetNetClasses().GetDefault();
}

View File

@ -48,6 +48,7 @@ using namespace std::placeholders;
#include <tool/tool_manager.h>
#include <tools/pcb_actions.h>
#include <tools/selection_tool.h>
#include <project/project_file.h> // LAST_PATH_TYPE
#include <view/view.h>
extern void SpreadFootprints( std::vector<MODULE*>* aFootprints,

View File

@ -136,7 +136,6 @@ void PCB_BASE_FRAME::SetBoard( BOARD* aBoard )
{
delete m_Pcb;
m_Pcb = aBoard;
m_Pcb->SetGeneralSettings( m_Settings );
wxCommandEvent e( BOARD_CHANGED );
ProcessEventLocally( e );
@ -277,13 +276,6 @@ BOARD_DESIGN_SETTINGS& PCB_BASE_FRAME::GetDesignSettings() const
}
void PCB_BASE_FRAME::SetDesignSettings( const BOARD_DESIGN_SETTINGS& aSettings )
{
wxASSERT( m_Pcb );
m_Pcb->SetDesignSettings( aSettings );
}
void PCB_BASE_FRAME::SetDrawBgColor( COLOR4D aColor )
{
m_drawBgColor= aColor;
@ -294,14 +286,14 @@ void PCB_BASE_FRAME::SetDrawBgColor( COLOR4D aColor )
const ZONE_SETTINGS& PCB_BASE_FRAME::GetZoneSettings() const
{
wxASSERT( m_Pcb );
return m_Pcb->GetZoneSettings();
return m_Pcb->GetDesignSettings().GetDefaultZoneSettings();
}
void PCB_BASE_FRAME::SetZoneSettings( const ZONE_SETTINGS& aSettings )
{
wxASSERT( m_Pcb );
m_Pcb->SetZoneSettings( aSettings );
m_Pcb->GetDesignSettings().SetDefaultZoneSettings( aSettings );
}
@ -735,8 +727,6 @@ void PCB_BASE_FRAME::ActivateGalCanvas()
GetCanvas()->GetViewControls(), config(), this );
}
SetBoard( m_Pcb );
if( m_toolManager )
m_toolManager->ResetTools( TOOL_BASE::GAL_SWITCH );

View File

@ -52,6 +52,7 @@
#include <kicad_string.h>
#include <pcb_draw_panel_gal.h>
#include <functional>
#include <project/project_file.h>
#include <settings/settings_manager.h>
#include <tool/tool_manager.h>
#include <tool/tool_dispatcher.h>
@ -369,6 +370,9 @@ PCB_EDIT_FRAME::~PCB_EDIT_FRAME()
void PCB_EDIT_FRAME::SetBoard( BOARD* aBoard )
{
if( m_Pcb )
m_Pcb->ClearProject();
PCB_BASE_EDIT_FRAME::SetBoard( aBoard );
aBoard->SetProject( &Prj() );
@ -497,39 +501,42 @@ void PCB_EDIT_FRAME::OnQuit( wxCommandEvent& event )
void PCB_EDIT_FRAME::RecordDRCExclusions()
{
m_drcExclusions.clear();
BOARD_DESIGN_SETTINGS& bds = GetBoard()->GetDesignSettings();
bds.m_DrcExclusions.clear();
for( MARKER_PCB* marker : GetBoard()->Markers() )
{
if( marker->IsExcluded() )
m_drcExclusions.insert( marker->Serialize() );
bds.m_DrcExclusions.insert( marker->Serialize() );
}
}
void PCB_EDIT_FRAME::ResolveDRCExclusions()
{
BOARD_DESIGN_SETTINGS& bds = GetBoard()->GetDesignSettings();
for( MARKER_PCB* marker : GetBoard()->Markers() )
{
auto i = m_drcExclusions.find( marker->Serialize() );
auto i = bds.m_DrcExclusions.find( marker->Serialize() );
if( i != m_drcExclusions.end() )
if( i != bds.m_DrcExclusions.end() )
{
marker->SetExcluded( true );
m_drcExclusions.erase( i );
bds.m_DrcExclusions.erase( i );
}
}
BOARD_COMMIT commit( this );
for( const wxString& exclusionData : m_drcExclusions )
for( const wxString& exclusionData : bds.m_DrcExclusions )
{
MARKER_PCB* marker = MARKER_PCB::Deserialize( exclusionData );
marker->SetExcluded( true );
commit.Add( marker );
}
m_drcExclusions.clear();
bds.m_DrcExclusions.clear();
commit.Push( wxEmptyString, false, false );
}
@ -847,10 +854,12 @@ void PCB_EDIT_FRAME::ShowChangedLanguage()
wxString PCB_EDIT_FRAME::GetLastPath( LAST_PATH_TYPE aType )
{
if( m_lastPath[ aType ].IsEmpty() )
PROJECT_FILE& project = Prj().GetProjectFile();
if( project.m_PcbLastPath[ aType ].IsEmpty() )
return wxEmptyString;
wxFileName absoluteFileName = m_lastPath[ aType ];
wxFileName absoluteFileName = project.m_PcbLastPath[ aType ];
wxFileName pcbFileName = GetBoard()->GetFileName();
absoluteFileName.MakeAbsolute( pcbFileName.GetPath() );
@ -860,14 +869,16 @@ wxString PCB_EDIT_FRAME::GetLastPath( LAST_PATH_TYPE aType )
void PCB_EDIT_FRAME::SetLastPath( LAST_PATH_TYPE aType, const wxString& aLastPath )
{
PROJECT_FILE& project = Prj().GetProjectFile();
wxFileName relativeFileName = aLastPath;
wxFileName pcbFileName = GetBoard()->GetFileName();
relativeFileName.MakeRelativeTo( pcbFileName.GetPath() );
if( relativeFileName.GetFullPath() != m_lastPath[ aType ] )
if( relativeFileName.GetFullPath() != project.m_PcbLastPath[ aType ] )
{
m_lastPath[ aType ] = relativeFileName.GetFullPath();
project.m_PcbLastPath[ aType ] = relativeFileName.GetFullPath();
SaveProjectSettings();
}
}

View File

@ -24,7 +24,6 @@
#include <unordered_map>
#include <map>
#include "pcb_base_edit_frame.h"
#include "config_params.h"
#include "undo_redo_container.h"
#include "zones.h"
@ -60,6 +59,7 @@ class IO_ERROR;
class FP_LIB_TABLE;
class BOARD_NETLIST_UPDATER;
class ACTION_MENU;
enum LAST_PATH_TYPE : unsigned int;
namespace PCB { struct IFACE; } // KIFACE_I is in pcbnew.cpp
@ -73,18 +73,6 @@ enum TRACK_ACTION_RESULT
TRACK_ACTION_NONE //!< TRACK_ACTION_NONE - Nothing to change
};
enum LAST_PATH_TYPE
{
LAST_PATH_NETLIST = 0,
LAST_PATH_STEP,
LAST_PATH_IDF,
LAST_PATH_VRML,
LAST_PATH_SPECCTRADSN,
LAST_PATH_GENCAD,
LAST_PATH_SIZE
};
/**
* PCB_EDIT_FRAME
* is the main frame for Pcbnew.
@ -102,11 +90,6 @@ class PCB_EDIT_FRAME : public PCB_BASE_EDIT_FRAME
ACTION_TOOLBAR* m_microWaveToolBar;
protected:
std::vector<PARAM_CFG*> m_projectFileParams;
wxString m_lastPath[ LAST_PATH_SIZE ];
std::set<wxString> m_drcExclusions;
/**
* Store the previous layer toolbar icon state information
@ -377,20 +360,6 @@ public:
#endif
/**
* Function GetProjectFileParameters
* returns a project file parameter list for Pcbnew.
* <p>
* Populate a project file parameter array specific to Pcbnew.
* Creating the parameter list at run time has the advantage of being able
* to define local variables. The old method of statically building the array
* at compile time requiring global variable definitions by design.
* </p>
* @return std::vector<PARAM_CFG*> - it is only good until SetBoard() is called, so
* don't keep it around past that event.
*/
std::vector<PARAM_CFG*>& GetProjectFileParameters();
/**
* Function SaveProjectSettings
* saves changes to the project settings to the project (.pro) file.

View File

@ -331,7 +331,6 @@ void PCB_LAYER_WIDGET::SetLayersManagerTabsText()
void PCB_LAYER_WIDGET::ReFillRender()
{
BOARD* board = myframe->GetBoard();
auto settings = board->GetDesignSettings();
ClearRenderRows();
@ -346,17 +345,6 @@ void PCB_LAYER_WIDGET::ReFillRender()
if( m_fp_editor_mode && !isAllowedInFpMode( renderRow.id ) )
continue;
// Don't remove microvia and bblind vias if they're not allowed: that's only a DRC
// setting (which might be set to ignore) and the user can add them irrespective of
// the setting.
/*
if( renderRow.id == LAYER_VIA_MICROVIA && !settings.m_MicroViasAllowed )
continue;
if( renderRow.id == LAYER_VIA_BBLIND && !settings.m_BlindBuriedViaAllowed )
continue;
*/
if( !renderRow.spacer )
{
renderRow.tooltip = wxGetTranslation( s_render_rows[row].tooltip );
@ -640,10 +628,6 @@ void PCB_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal
brd->SetVisibleLayers( visibleLayers );
// Layer visibility is not stored in .kicad_mod files
if( !m_fp_editor_mode )
myframe->OnModify();
if( myframe->GetCanvas() )
myframe->GetCanvas()->GetView()->SetLayerVisible( aLayer, isVisible );
}
@ -685,14 +669,6 @@ void PCB_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled )
BOARD* brd = myframe->GetBoard();
wxASSERT( aId > GAL_LAYER_ID_START && aId < GAL_LAYER_ID_END );
if( myframe->IsType( FRAME_PCB_EDITOR ) )
{
// The layer visibility status is saved in the board file so set the board
// modified state so the user has the option to save the changes.
if( brd->IsElementVisible( static_cast<GAL_LAYER_ID>( aId ) ) != isEnabled )
myframe->OnModify();
}
// Grid is not set through the board visibility
if( aId == LAYER_GRID )
myframe->SetGridVisibility( isEnabled );

View File

@ -577,6 +577,7 @@ BOARD* PCB_PARSER::parseBOARD_unchecked()
case T_net_class:
parseNETCLASS();
m_board->m_LegacyNetclassesLoaded = true;
break;
case T_gr_arc:
@ -1253,6 +1254,7 @@ void PCB_PARSER::parseLayers()
LSET enabledLayers;
int copperLayerCount = 0;
LAYER layer;
bool anyHidden = false;
std::unordered_map< std::string, std::string > v3_layer_names;
std::vector<LAYER> cu;
@ -1292,6 +1294,8 @@ void PCB_PARSER::parseLayers()
if( it->m_visible )
visibleLayers.set( it->m_number );
else
anyHidden = true;
m_board->SetLayerDescr( PCB_LAYER_ID( it->m_number ), *it );
@ -1341,6 +1345,8 @@ void PCB_PARSER::parseLayers()
if( layer.m_visible )
visibleLayers.set( layer.m_number );
else
anyHidden = true;
m_board->SetLayerDescr( it->second, layer );
@ -1364,8 +1370,10 @@ void PCB_PARSER::parseLayers()
m_board->SetCopperLayerCount( copperLayerCount );
m_board->SetEnabledLayers( enabledLayers );
// call SetEnabledLayers before SetVisibleLayers()
m_board->SetVisibleLayers( visibleLayers );
// Only set this if any layers were explicitly marked as hidden. Otherwise, we want to leave
// this alone; default visibility will show everything
if( anyHidden )
m_board->m_LegacyVisibleLayers = visibleLayers;
}
@ -1433,9 +1441,9 @@ void PCB_PARSER::parseSetup()
wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as setup." ) );
T token;
NETCLASS* defaultNetClass = m_board->GetDesignSettings().GetDefault();
BOARD_DESIGN_SETTINGS& designSettings = m_board->GetDesignSettings();
ZONE_SETTINGS zoneSettings = m_board->GetZoneSettings();
NETCLASS* defaultNetClass = m_board->GetDesignSettings().GetDefault();
BOARD_DESIGN_SETTINGS& designSettings = m_board->GetDesignSettings();
ZONE_SETTINGS& zoneSettings = designSettings.GetDefaultZoneSettings();
// Missing soldermask min width value means that the user has set the value to 0 and
// not the default value (0.25mm)
@ -1461,67 +1469,80 @@ void PCB_PARSER::parseSetup()
case T_user_trace_width:
designSettings.m_TrackWidthList.push_back( parseBoardUnits( T_user_trace_width ) );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_trace_clearance:
defaultNetClass->SetClearance( parseBoardUnits( T_trace_clearance ) );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_zone_clearance:
zoneSettings.m_ZoneClearance = parseBoardUnits( T_zone_clearance );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_zone_45_only:
zoneSettings.m_Zone_45_Only = parseBool();
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_clearance_min:
designSettings.m_MinClearance = parseBoardUnits( T_clearance_min );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_trace_min:
designSettings.m_TrackMinWidth = parseBoardUnits( T_trace_min );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_via_size:
defaultNetClass->SetViaDiameter( parseBoardUnits( T_via_size ) );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_via_drill:
defaultNetClass->SetViaDrill( parseBoardUnits( T_via_drill ) );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_via_min_annulus:
designSettings.m_ViasMinAnnulus = parseBoardUnits( T_via_min_annulus );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_via_min_size:
designSettings.m_ViasMinSize = parseBoardUnits( T_via_min_size );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_through_hole_min:
designSettings.m_MinThroughDrill = parseBoardUnits( T_through_hole_min );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
// Legacy token for T_through_hole_min
case T_via_min_drill:
designSettings.m_MinThroughDrill = parseBoardUnits( T_via_min_drill );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_hole_to_hole_min:
designSettings.m_HoleToHoleMin = parseBoardUnits( T_hole_to_hole_min );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
@ -1530,37 +1551,44 @@ void PCB_PARSER::parseSetup()
int viaSize = parseBoardUnits( "user via size" );
int viaDrill = parseBoardUnits( "user via drill" );
designSettings.m_ViasDimensionsList.emplace_back( VIA_DIMENSION( viaSize, viaDrill ) );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
}
break;
case T_uvia_size:
defaultNetClass->SetuViaDiameter( parseBoardUnits( T_uvia_size ) );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_uvia_drill:
defaultNetClass->SetuViaDrill( parseBoardUnits( T_uvia_drill ) );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_uvias_allowed:
designSettings.m_MicroViasAllowed = parseBool();
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_blind_buried_vias_allowed:
designSettings.m_BlindBuriedViaAllowed = parseBool();
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_uvia_min_size:
designSettings.m_MicroViasMinSize = parseBoardUnits( T_uvia_min_size );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_uvia_min_drill:
designSettings.m_MicroViasMinDrill = parseBoardUnits( T_uvia_min_drill );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
@ -1570,49 +1598,58 @@ void PCB_PARSER::parseSetup()
int gap = parseBoardUnits( "user diff-pair gap" );
int viaGap = parseBoardUnits( "user diff-pair via gap" );
designSettings.m_DiffPairDimensionsList.emplace_back( DIFF_PAIR_DIMENSION( width, gap, viaGap ) );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
}
break;
case T_segment_width: // note: legacy (pre-6.0) token
designSettings.m_LineThickness[ LAYER_CLASS_COPPER ] = parseBoardUnits( T_segment_width );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_edge_width: // note: legacy (pre-6.0) token
designSettings.m_LineThickness[ LAYER_CLASS_EDGES ] = parseBoardUnits( T_edge_width );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_mod_edge_width: // note: legacy (pre-6.0) token
designSettings.m_LineThickness[ LAYER_CLASS_SILK ] = parseBoardUnits( T_mod_edge_width );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_pcb_text_width: // note: legacy (pre-6.0) token
designSettings.m_TextThickness[ LAYER_CLASS_COPPER ] = parseBoardUnits( T_pcb_text_width );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_mod_text_width: // note: legacy (pre-6.0) token
designSettings.m_TextThickness[ LAYER_CLASS_SILK ] = parseBoardUnits( T_mod_text_width );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_pcb_text_size: // note: legacy (pre-6.0) token
designSettings.m_TextSize[ LAYER_CLASS_COPPER ].x = parseBoardUnits( "pcb text width" );
designSettings.m_TextSize[ LAYER_CLASS_COPPER ].y = parseBoardUnits( "pcb text height" );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_mod_text_size: // note: legacy (pre-6.0) token
designSettings.m_TextSize[ LAYER_CLASS_SILK ].x = parseBoardUnits( "module text width" );
designSettings.m_TextSize[ LAYER_CLASS_SILK ].y = parseBoardUnits( "module text height" );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_defaults:
parseDefaults( designSettings );
m_board->m_LegacyDesignSettingsLoaded = true;
break;
case T_pad_size:
@ -1621,6 +1658,7 @@ void PCB_PARSER::parseSetup()
sz.SetWidth( parseBoardUnits( "master pad width" ) );
sz.SetHeight( parseBoardUnits( "master pad height" ) );
designSettings.m_Pad_Master.SetSize( sz );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
}
break;
@ -1629,27 +1667,32 @@ void PCB_PARSER::parseSetup()
{
int drillSize = parseBoardUnits( T_pad_drill );
designSettings.m_Pad_Master.SetDrillSize( wxSize( drillSize, drillSize ) );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
}
break;
case T_pad_to_mask_clearance:
designSettings.m_SolderMaskMargin = parseBoardUnits( T_pad_to_mask_clearance );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_solder_mask_min_width:
designSettings.m_SolderMaskMinWidth = parseBoardUnits( T_solder_mask_min_width );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_pad_to_paste_clearance:
designSettings.m_SolderPasteMargin = parseBoardUnits( T_pad_to_paste_clearance );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_pad_to_paste_clearance_ratio:
designSettings.m_SolderPasteMarginRatio = parseDouble( T_pad_to_paste_clearance_ratio );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
@ -1657,8 +1700,9 @@ void PCB_PARSER::parseSetup()
{
int x = parseBoardUnits( "auxiliary origin X" );
int y = parseBoardUnits( "auxiliary origin Y" );
// m_board->SetAuxOrigin( wxPoint( x, y ) ); gets overwritten via SetDesignSettings below
designSettings.m_AuxOrigin = wxPoint( x, y );
// Aux origin still stored in board for the moment
//m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
}
break;
@ -1667,24 +1711,36 @@ void PCB_PARSER::parseSetup()
{
int x = parseBoardUnits( "grid origin X" );
int y = parseBoardUnits( "grid origin Y" );
// m_board->SetGridOrigin( wxPoint( x, y ) ); gets overwritten SetDesignSettings below
designSettings.m_GridOrigin = wxPoint( x, y );
// Grid origin still stored in board for the moment
//m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
}
break;
// Stored in board prior to 6.0
case T_visible_elements:
designSettings.SetVisibleElements( parseHex() | MIN_VISIBILITY_MASK );
NeedRIGHT();
{
m_board->m_LegacyVisibleItems.reset();
int visible = parseHex() | MIN_VISIBILITY_MASK;
for( size_t i = 0; i < sizeof( int ) * CHAR_BIT; i++ )
m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
NeedRIGHT();
}
break;
case T_max_error:
designSettings.m_MaxError = parseBoardUnits( T_max_error );
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
case T_filled_areas_thickness:
designSettings.m_ZoneUseNoOutlineInFill = not parseBool();
m_board->m_LegacyDesignSettingsLoaded = true;
NeedRIGHT();
break;
@ -1707,9 +1763,6 @@ void PCB_PARSER::parseSetup()
Unexpected( CurText() );
}
}
//m_board->SetDesignSettings( designSettings );
m_board->SetZoneSettings( zoneSettings );
}
@ -1925,7 +1978,7 @@ void PCB_PARSER::parseNETCLASS()
NeedRIGHT();
}
if( !m_board->GetDesignSettings().m_NetClasses.Add( nc ) )
if( !m_board->GetDesignSettings().GetNetClasses().Add( nc ) )
{
// Must have been a name conflict, this is a bad board file.
// User may have done a hand edit to the file.

View File

@ -46,6 +46,7 @@
#include <invoke_pcb_dialog.h>
#include <wildcards_and_files_ext.h>
#include <widgets/paged_dialog.h>
#include <project/project_file.h>
void PCB_EDIT_FRAME::On3DShapeLibWizard( wxCommandEvent& event )
@ -77,7 +78,9 @@ bool PCB_EDIT_FRAME::LoadProjectSettings()
{
wxLogDebug( wxT( "Loading project '%s' settings." ), GetChars( Prj().GetProjectFullName() ) );
bool rc = Prj().ConfigLoad( Kiface().KifaceSearch(), GROUP_PCB, GetProjectFileParameters() );
PROJECT_FILE& project = Prj().GetProjectFile();
BASE_SCREEN::m_PageLayoutDescrFileName = project.m_PageLayoutDescrFile;
// Load the page layout decr file, from the filename stored in
// BASE_SCREEN::m_PageLayoutDescrFileName, read in config project file
@ -88,7 +91,7 @@ bool PCB_EDIT_FRAME::LoadProjectSettings()
pglayout.SetPageLayout( filename );
return rc;
return true;
}
@ -105,45 +108,12 @@ void PCB_EDIT_FRAME::SaveProjectSettings()
if( !IsWritable( fn ) )
return;
wxString pro_name = fn.GetFullPath();
PROJECT_FILE& project = Prj().GetProjectFile();
// TODO: Can this be pulled out of BASE_SCREEN?
project.m_PageLayoutDescrFile = BASE_SCREEN::m_PageLayoutDescrFileName;
RecordDRCExclusions();
Prj().ConfigSave( Kiface().KifaceSearch(), GROUP_PCB, GetProjectFileParameters(), pro_name );
}
std::vector<PARAM_CFG*>& PCB_EDIT_FRAME::GetProjectFileParameters()
{
m_projectFileParams.clear();
// This one cannot be cached because some settings are going to/from the BOARD,
// so pointers into that cannot be saved for long.
m_projectFileParams.push_back( new PARAM_CFG_FILENAME( wxT( "PageLayoutDescrFile" ),
&BASE_SCREEN::m_PageLayoutDescrFileName ) );
m_projectFileParams.push_back( new PARAM_CFG_FILENAME( wxT( "LastNetListRead" ),
&m_lastPath[ LAST_PATH_NETLIST ] ) );
m_projectFileParams.push_back( new PARAM_CFG_FILENAME( wxT( "LastSTEPExportPath" ),
&m_lastPath[ LAST_PATH_STEP ] ) );
m_projectFileParams.push_back( new PARAM_CFG_FILENAME( wxT( "LastIDFExportPath" ),
&m_lastPath[ LAST_PATH_IDF ] ) );
m_projectFileParams.push_back( new PARAM_CFG_FILENAME( wxT( "LastVRMLExportPath" ),
&m_lastPath[ LAST_PATH_VRML ] ) );
m_projectFileParams.push_back( new PARAM_CFG_FILENAME( wxT( "LastSpecctraDSNExportPath" ),
&m_lastPath[ LAST_PATH_SPECCTRADSN ] ) );
m_projectFileParams.push_back( new PARAM_CFG_FILENAME( wxT( "LastGenCADExportPath" ),
&m_lastPath[ LAST_PATH_GENCAD ] ) );
m_projectFileParams.push_back( new PARAM_CFG_WXSTRING_SET( wxT( "DRCExclusion" ),
&m_drcExclusions ) );
GetBoard()->GetDesignSettings().AppendConfigs( GetBoard(), &m_projectFileParams);
return m_projectFileParams;
GetSettingsManager()->SaveProject();
}

View File

@ -126,7 +126,7 @@ PNS_PCBNEW_RULE_RESOLVER::PNS_PCBNEW_RULE_RESOLVER( BOARD* aBoard, PNS::ROUTER*
ent.coupledNet = DpCoupledNet( i );
wxString netClassName = ni->GetClassName();
NETCLASSPTR nc = m_board->GetDesignSettings().m_NetClasses.Find( netClassName );
NETCLASSPTR nc = m_board->GetDesignSettings().GetNetClasses().Find( netClassName );
int clearance = nc->GetClearance();
ent.clearance = clearance;
@ -154,7 +154,7 @@ PNS_PCBNEW_RULE_RESOLVER::PNS_PCBNEW_RULE_RESOLVER( BOARD* aBoard, PNS::ROUTER*
}
}
auto defaultRule = m_board->GetDesignSettings().m_NetClasses.Find ("Default");
auto defaultRule = m_board->GetDesignSettings().GetNetClasses().Find ("Default");
if( defaultRule )
{

View File

@ -89,12 +89,12 @@ void SIZES_SETTINGS::Init( BOARD* aBoard, ITEM* aStartItem, int aNet )
if( ni )
{
wxString netClassName = ni->GetClassName();
netClass = bds.m_NetClasses.Find( netClassName );
netClass = bds.GetNetClasses().Find( netClassName );
}
}
if( !netClass )
netClass = bds.m_NetClasses.GetDefault();
netClass = bds.GetNetClasses().GetDefault();
m_trackWidth = 0;

View File

@ -1430,7 +1430,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
//-----< output vias used in netclasses >-----------------------------------
{
NETCLASSES& nclasses = aBoard->GetDesignSettings().m_NetClasses;
NETCLASSES& nclasses = aBoard->GetDesignSettings().GetNetClasses();
// Assume the netclass vias are all the same kind of thru, blind, or buried vias.
// This is in lieu of either having each netclass via have its own layer pair in
@ -1641,7 +1641,7 @@ void SPECCTRA_DB::FromBOARD( BOARD* aBoard )
//-----<output NETCLASSs>----------------------------------------------------
NETCLASSES& nclasses = aBoard->GetDesignSettings().m_NetClasses;
NETCLASSES& nclasses = aBoard->GetDesignSettings().GetNetClasses();
exportNETCLASS( nclasses.GetDefault(), aBoard );

View File

@ -499,7 +499,7 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard )
GetChars( psid ) ) );
}
NETCLASSPTR netclass = aBoard->GetDesignSettings().m_NetClasses.GetDefault();
NETCLASSPTR netclass = aBoard->GetDesignSettings().GetNetClasses().GetDefault();
int via_drill_default = netclass->GetViaDrill();

View File

@ -96,11 +96,16 @@ HANDLE_EXCEPTIONS(BOARD::TracksInNetBetweenPoints)
}
%{
#include <layers_id_colors_and_visibility.h>
#include <pcbnew_scripting_helpers.h>
%}
// std::vector templates
%template(VIA_DIMENSION_Vector) std::vector<VIA_DIMENSION>;
// Do not permit default BOARD ctor since it won't initialize the project
%ignore BOARD::BOARD();
%include class_board.h
%{
#include <class_board.h>
@ -123,11 +128,25 @@ HANDLE_EXCEPTIONS(BOARD::TracksInNetBetweenPoints)
%extend BOARD
{
// NOTE: this does not generate a ctor, despite swig docs saying it should. Not sure why.
// Because of this, we use the __init__ override hack below.
// BOARD()
// {
// return CreateEmptyBoard();
// }
// BOARD_ITEM_CONTAINER's interface functions will be implemented by SWIG
// automatically and inherited by the python wrapper class.
%pythoncode
%{
def __init__(self, *args):
this = CreateEmptyBoard()
try:
self.this.append(this)
except:
self.this = this
def GetModules(self): return self.Modules()
def GetDrawings(self): return self.Drawings()

View File

@ -42,9 +42,19 @@
#include <pcbnew.h>
#include <pcbnew_scripting_helpers.h>
#include <project.h>
#include <settings/settings_manager.h>
#include <wildcards_and_files_ext.h>
static PCB_EDIT_FRAME* s_PcbEditFrame = NULL;
/**
* We need to track the loaded PROJECTs for each loaded BOARD here, since in Python you can
* easily load more than one board if desired.
*/
static std::map<wxString, PROJECT*> s_Projects;
static SETTINGS_MANAGER* s_SettingsManager = nullptr;
BOARD* GetBoard()
{
if( s_PcbEditFrame )
@ -73,17 +83,72 @@ BOARD* LoadBoard( wxString& aFileName )
}
SETTINGS_MANAGER* GetSettingsManager()
{
if( !s_SettingsManager )
s_SettingsManager = new SETTINGS_MANAGER;
return s_SettingsManager;
}
PROJECT* GetDefaultProject()
{
PROJECT* project = nullptr;
if( s_Projects.count( "" ) )
project = s_Projects.at( "" );
else
{
GetSettingsManager()->LoadProject( "" );
project = GetSettingsManager()->GetProject( "" );
s_Projects[""] = project;
}
return project;
}
BOARD* LoadBoard( wxString& aFileName, IO_MGR::PCB_FILE_T aFormat )
{
wxFileName pro = aFileName;
pro.SetExt( ProjectFileExtension );
pro.MakeAbsolute();
wxString projectPath = pro.GetFullPath();
PROJECT* project = nullptr;
if( s_Projects.count( projectPath ) )
project = s_Projects.at( projectPath );
else if( GetSettingsManager()->LoadProject( projectPath ) )
{
project = GetSettingsManager()->GetProject( projectPath );
s_Projects[projectPath] = project;
}
// Board cannot be loaded without a project, so create the default project
if( !project )
project = GetDefaultProject();
BOARD* brd = IO_MGR::Load( aFormat, aFileName );
if( brd )
{
brd->SetProject( project );
brd->BuildConnectivity();
brd->BuildListOfNets();
brd->SynchronizeNetsAndNetClasses();
}
return brd;
}
BOARD* CreateEmptyBoard()
{
BOARD* brd = new BOARD();
brd->SetProject( GetDefaultProject() );
return brd;
}
@ -97,6 +162,13 @@ bool SaveBoard( wxString& aFileName, BOARD* aBoard, IO_MGR::PCB_FILE_T aFormat )
IO_MGR::Save( aFormat, aFileName, aBoard, NULL );
wxFileName pro = aFileName;
pro.SetExt( ProjectFileExtension );
pro.MakeAbsolute();
wxString projectPath = pro.GetFullPath();
GetSettingsManager()->SaveProject( pro.GetFullPath() );
return true;
}

View File

@ -45,6 +45,12 @@ BOARD* LoadBoard( wxString& aFileName, IO_MGR::PCB_FILE_T aFormat );
// Default LoadBoard() to load .kicad_pcb files:.
BOARD* LoadBoard( wxString& aFileName );
/**
* Constructs a default BOARD with a tempoary (no filename) project
* @return the created board
*/
BOARD* CreateEmptyBoard();
// Boards can be saved only as .kicad_pcb file format,
// so no option to choose the file format.
bool SaveBoard( wxString& aFileName, BOARD* aBoard );

View File

@ -32,8 +32,8 @@
#include <board_commit.h>
#include <class_board.h>
#include <class_module.h>
#include <class_track.h>
#include <class_pcb_target.h>
#include <class_track.h>
#include <class_zone.h>
#include <collectors.h>
#include <confirm.h>
@ -52,6 +52,7 @@
#include <pcbnew_id.h>
#include <pcbnew_settings.h>
#include <project.h>
#include <project/project_file.h> // LAST_PATH_TYPE
#include <tool/tool_manager.h>
#include <tools/tool_event_utils.h>
#include <view/view_controls.h>

View File

@ -883,7 +883,7 @@ int PCBNEW_CONTROL::AppendBoard( PLUGIN& pi, wxString& fileName )
props["page_width"] = xbuf;
props["page_height"] = ybuf;
editFrame->GetDesignSettings().m_NetClasses.Clear();
editFrame->GetDesignSettings().GetNetClasses().Clear();
pi.Load( fileName, brd, &props );
}
catch( const IO_ERROR& ioe )

View File

@ -32,7 +32,8 @@
#include <layers_id_colors_and_visibility.h>
#include <zones.h>
#include <wx/dataview.h>
class wxDataViewListCtrl;
enum class ZONE_FILL_MODE
{

View File

@ -228,25 +228,6 @@ std::unique_ptr<BOARD> MakeBoard( const std::vector<COURTYARD_INVALID_TEST_MODUL
}
/**
* Get a #BOARD_DESIGN_SETTINGS object that will cause DRC to
* check for courtyard invalidity
*/
static BOARD_DESIGN_SETTINGS GetOverlapCheckDesignSettings()
{
BOARD_DESIGN_SETTINGS des_settings;
// do the overlap tests - that's a different test, but if not set,
// the invalid courtyard checks don't run either
des_settings.m_DRCSeverities[ DRCE_OVERLAPPING_FOOTPRINTS ] = RPT_SEVERITY_ERROR;
// we will also check for missing courtyards here
des_settings.m_DRCSeverities[ DRCE_MISSING_COURTYARD ] = RPT_SEVERITY_ERROR;
return des_settings;
}
/**
* Check if a #MARKER_PCB is described by a particular #COURTYARD_INVALID_INFO object.
*/
@ -301,7 +282,14 @@ void DoCourtyardInvalidTest( const COURTYARD_INVALID_CASE& aCase,
// Dump if env var set
aDumper.DumpBoardToFile( *board, aCase.m_case_name );
board->SetDesignSettings( GetOverlapCheckDesignSettings() );
BOARD_DESIGN_SETTINGS& bds = board->GetDesignSettings();
// do the overlap tests - that's a different test, but if not set,
// the invalid courtyard checks don't run either
bds.m_DRCSeverities[ DRCE_OVERLAPPING_FOOTPRINTS ] = RPT_SEVERITY_ERROR;
// we will also check for missing courtyards here
bds.m_DRCSeverities[ DRCE_MISSING_COURTYARD ] = RPT_SEVERITY_ERROR;
// list of markers to collect
std::vector<std::unique_ptr<MARKER_PCB>> markers;

View File

@ -441,21 +441,6 @@ static void CheckCollisionsMatchExpected( BOARD& aBoard,
}
/**
* Get a #BOARD_DESIGN_SETTINGS object that will cause DRC to check for courtyard overlaps
*/
static BOARD_DESIGN_SETTINGS GetOverlapCheckDesignSettings()
{
BOARD_DESIGN_SETTINGS des_settings;
des_settings.m_DRCSeverities[ DRCE_OVERLAPPING_FOOTPRINTS ] = RPT_SEVERITY_ERROR;
// we might not always have courtyards - that's a separate test
des_settings.m_DRCSeverities[ DRCE_MISSING_COURTYARD ] = RPT_SEVERITY_IGNORE;
return des_settings;
}
/**
* Run a single courtyard overlap testcase
* @param aCase The testcase to run.
@ -468,7 +453,12 @@ static void DoCourtyardOverlapTest( const COURTYARD_OVERLAP_TEST_CASE& aCase,
// Dump if env var set
aDumper.DumpBoardToFile( *board, aCase.m_case_name );
board->SetDesignSettings( GetOverlapCheckDesignSettings() );
BOARD_DESIGN_SETTINGS& bds = board->GetDesignSettings();
bds.m_DRCSeverities[ DRCE_OVERLAPPING_FOOTPRINTS ] = RPT_SEVERITY_ERROR;
// we might not always have courtyards - that's a separate test
bds.m_DRCSeverities[ DRCE_MISSING_COURTYARD ] = RPT_SEVERITY_IGNORE;
// list of markers to collect
std::vector<std::unique_ptr<MARKER_PCB>> markers;

View File

@ -69,7 +69,7 @@ public:
if( m_exec_context.m_verbose )
std::cout << "Running DRC check: " << getRunnerIntro() << std::endl;
aBoard.SetDesignSettings( getDesignSettings() );
setDesignSettings( aBoard.GetDesignSettings() );
std::vector<std::unique_ptr<MARKER_PCB>> markers;
@ -101,9 +101,10 @@ private:
virtual std::string getRunnerIntro() const = 0;
/**
* Get suitable design settings for this DRC runner
* Set suitable design settings for this DRC runner
* @param aSettings is a reference to the design settings object of the board under test
*/
virtual BOARD_DESIGN_SETTINGS getDesignSettings() const = 0;
virtual void setDesignSettings( BOARD_DESIGN_SETTINGS& aSettings ) const = 0;
virtual std::unique_ptr<DRC_TEST_PROVIDER> createDrcProvider(
BOARD& aBoard, DRC_TEST_PROVIDER::MARKER_HANDLER aHandler ) = 0;
@ -157,13 +158,10 @@ private:
return "Courtyard overlap";
}
BOARD_DESIGN_SETTINGS getDesignSettings() const override
void setDesignSettings( BOARD_DESIGN_SETTINGS& aSettings ) const override
{
BOARD_DESIGN_SETTINGS des_settings;
des_settings.m_DRCSeverities[ DRCE_MISSING_COURTYARD ] = RPT_SEVERITY_IGNORE;
des_settings.m_DRCSeverities[ DRCE_OVERLAPPING_FOOTPRINTS ] = RPT_SEVERITY_ERROR;
return des_settings;
aSettings.m_DRCSeverities[ DRCE_MISSING_COURTYARD ] = RPT_SEVERITY_IGNORE;
aSettings.m_DRCSeverities[ DRCE_OVERLAPPING_FOOTPRINTS ] = RPT_SEVERITY_ERROR;
}
std::unique_ptr<DRC_TEST_PROVIDER> createDrcProvider(
@ -194,13 +192,10 @@ private:
return "Courtyard missing";
}
BOARD_DESIGN_SETTINGS getDesignSettings() const override
void setDesignSettings( BOARD_DESIGN_SETTINGS& aSettings ) const override
{
BOARD_DESIGN_SETTINGS des_settings;
des_settings.m_DRCSeverities[ DRCE_MISSING_COURTYARD ] = RPT_SEVERITY_ERROR;
des_settings.m_DRCSeverities[ DRCE_OVERLAPPING_FOOTPRINTS ] = RPT_SEVERITY_IGNORE;
return des_settings;
aSettings.m_DRCSeverities[ DRCE_MISSING_COURTYARD ] = RPT_SEVERITY_ERROR;
aSettings.m_DRCSeverities[ DRCE_OVERLAPPING_FOOTPRINTS ] = RPT_SEVERITY_IGNORE;
}
std::unique_ptr<DRC_TEST_PROVIDER> createDrcProvider(