Add the ability to edit advanced config

If you set the env var KICAD_EDIT_ADVANCED_CFG=1, you get a new menu
option in the KiCad project window's Edit menu.  Lets you modify the
settings for advanced config graphically without having to
remember/lookup the magic incantation
This commit is contained in:
Seth Hillbrand 2025-08-14 15:36:42 -07:00
parent 7c499f499d
commit 17d9ff4fe7
11 changed files with 530 additions and 92 deletions

View File

@ -186,13 +186,13 @@ wxString dumpParamCfg( const PARAM_CFG& aParam )
/**
* Dump the configs in the given array to trace.
*/
static void dumpCfg( const std::vector<PARAM_CFG*>& aArray )
static void dumpCfg( const std::vector<std::unique_ptr<PARAM_CFG>>& aArray )
{
// only dump if we need to
if( !wxLog::IsAllowedTraceMask( AdvancedConfigMask ) )
return;
for( const PARAM_CFG* param : aArray )
for( const auto& param : aArray )
{
wxLogTrace( AdvancedConfigMask, dumpParamCfg( *param ) );
}
@ -326,6 +326,21 @@ const ADVANCED_CFG& ADVANCED_CFG::GetCfg()
}
void ADVANCED_CFG::Reload()
{
loadFromConfigFile();
}
void ADVANCED_CFG::Save()
{
wxFileName k_advanced = getAdvancedCfgFilename();
wxFileConfig file_cfg( wxS( "" ), wxS( "" ), k_advanced.GetFullPath() );
wxConfigSaveSetups( &file_cfg, m_entries );
}
void ADVANCED_CFG::loadFromConfigFile()
{
const wxFileName k_advanced = getAdvancedCfgFilename();
@ -355,270 +370,268 @@ void ADVANCED_CFG::loadFromConfigFile()
void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
{
std::vector<PARAM_CFG*> configParams;
m_entries.clear();
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::ExtraFillMargin,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::ExtraFillMargin,
&m_ExtraClearance,
m_ExtraClearance, 0.0, 1.0 ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableCreepageSlot,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::EnableCreepageSlot,
&m_EnableCreepageSlot, m_EnableCreepageSlot ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DRCEpsilon,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::DRCEpsilon,
&m_DRCEpsilon, m_DRCEpsilon, 0.0, 1.0 ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DRCSliverWidthTolerance,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::DRCSliverWidthTolerance,
&m_SliverWidthTolerance, m_SliverWidthTolerance,
0.01, 0.25 ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DRCSliverMinimumLength,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::DRCSliverMinimumLength,
&m_SliverMinimumLength, m_SliverMinimumLength,
1e-9, 10 ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DRCSliverAngleTolerance,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::DRCSliverAngleTolerance,
&m_SliverAngleTolerance, m_SliverAngleTolerance,
1.0, 90.0 ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::HoleWallThickness,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::HoleWallThickness,
&m_HoleWallThickness, m_HoleWallThickness,
0.0, 1.0 ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::CoroutineStackSize,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::CoroutineStackSize,
&m_CoroutineStackSize, AC_STACK::default_stack,
AC_STACK::min_stack, AC_STACK::max_stack ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::UpdateUIEventInterval,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::UpdateUIEventInterval,
&m_UpdateUIEventInterval, m_UpdateUIEventInterval,
-1, 100000 ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowRouterDebugGraphics,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::ShowRouterDebugGraphics,
&m_ShowRouterDebugGraphics,
m_ShowRouterDebugGraphics ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableRouterDump,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::EnableRouterDump,
&m_EnableRouterDump, m_EnableRouterDump ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::HyperZoom,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::HyperZoom,
&m_HyperZoom, m_HyperZoom ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::CompactFileSave,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::CompactFileSave,
&m_CompactSave, m_CompactSave ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DrawArcAccuracy,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::DrawArcAccuracy,
&m_DrawArcAccuracy, m_DrawArcAccuracy,
0.0, 100000.0 ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::DrawArcCenterStartEndMaxAngle,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::DrawArcCenterStartEndMaxAngle,
&m_DrawArcCenterMaxAngle,
m_DrawArcCenterMaxAngle, 0.0, 100000.0 ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::MaxTangentTrackAngleDeviation,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::MaxTangentTrackAngleDeviation,
&m_MaxTangentAngleDeviation,
m_MaxTangentAngleDeviation, 0.0, 90.0 ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::MaxTrackLengthToKeep,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::MaxTrackLengthToKeep,
&m_MaxTrackLengthToKeep, m_MaxTrackLengthToKeep,
0.0, 1.0 ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ExtraZoneDisplayModes,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::ExtraZoneDisplayModes,
&m_ExtraZoneDisplayModes,
m_ExtraZoneDisplayModes ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::StrokeTriangulation,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::StrokeTriangulation,
&m_DrawTriangulationOutlines,
m_DrawTriangulationOutlines ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::MinPlotPenWidth,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::MinPlotPenWidth,
&m_MinPlotPenWidth, m_MinPlotPenWidth,
0.0, 1.0 ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::DebugZoneFiller,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::DebugZoneFiller,
&m_DebugZoneFiller, m_DebugZoneFiller ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::DebugPDFWriter,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::DebugPDFWriter,
&m_DebugPDFWriter, m_DebugPDFWriter ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::SmallDrillMarkSize,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::SmallDrillMarkSize,
&m_SmallDrillMarkSize, m_SmallDrillMarkSize,
0.0, 3.0 ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::HotkeysDumper,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::HotkeysDumper,
&m_HotkeysDumper, m_HotkeysDumper ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::DrawBoundingBoxes,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::DrawBoundingBoxes,
&m_DrawBoundingBoxes, m_DrawBoundingBoxes ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowPcbnewExportNetlist,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::ShowPcbnewExportNetlist,
&m_ShowPcbnewExportNetlist,
m_ShowPcbnewExportNetlist ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::Skip3DModelFileCache,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::Skip3DModelFileCache,
&m_Skip3DModelFileCache, m_Skip3DModelFileCache ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::Skip3DModelMemoryCache,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::Skip3DModelMemoryCache,
&m_Skip3DModelMemoryCache,
m_Skip3DModelMemoryCache ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::HideVersionFromTitle,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::HideVersionFromTitle,
&m_HideVersionFromTitle, m_HideVersionFromTitle ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowRepairSchematic,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::ShowRepairSchematic,
&m_ShowRepairSchematic, m_ShowRepairSchematic ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ShowEventCounters,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::ShowEventCounters,
&m_ShowEventCounters, m_ShowEventCounters ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::AllowManualCanvasScale,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::AllowManualCanvasScale,
&m_AllowManualCanvasScale,
m_AllowManualCanvasScale ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::V3DRT_BevelHeight_um,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::V3DRT_BevelHeight_um,
&m_3DRT_BevelHeight_um, m_3DRT_BevelHeight_um,
0, std::numeric_limits<int>::max(),
AC_GROUPS::V3D_RayTracing ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::V3DRT_BevelExtentFactor,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::V3DRT_BevelExtentFactor,
&m_3DRT_BevelExtentFactor,
m_3DRT_BevelExtentFactor, 0.0, 100.0,
AC_GROUPS::V3D_RayTracing ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::Use3DConnexionDriver,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::Use3DConnexionDriver,
&m_Use3DConnexionDriver, m_Use3DConnexionDriver ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::IncrementalConnectivity,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::IncrementalConnectivity,
&m_IncrementalConnectivity,
m_IncrementalConnectivity ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::DisambiguationTime,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::DisambiguationTime,
&m_DisambiguationMenuDelay,
m_DisambiguationMenuDelay,
50, 10000 ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnablePcbDesignBlocks, &m_EnablePcbDesignBlocks,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::EnablePcbDesignBlocks, &m_EnablePcbDesignBlocks,
m_EnablePcbDesignBlocks ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableGenerators,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::EnableGenerators,
&m_EnableGenerators, m_EnableGenerators ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableAPILogging,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::EnableAPILogging,
&m_EnableAPILogging, m_EnableAPILogging ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableLibWithText,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::EnableLibWithText,
&m_EnableLibWithText, m_EnableLibWithText ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableLibDir,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::EnableLibDir,
&m_EnableLibDir, m_EnableLibDir ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::PcbSelectionVisibilityRatio,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::PcbSelectionVisibilityRatio,
&m_PcbSelectionVisibilityRatio,
m_PcbSelectionVisibilityRatio, 0.0, 1.0 ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::FontErrorSize,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::FontErrorSize,
&m_FontErrorSize,
m_FontErrorSize, 0.01, 100 ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::OcePluginLinearDeflection,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::OcePluginLinearDeflection,
&m_OcePluginLinearDeflection,
m_OcePluginLinearDeflection, 0.01, 1.0 ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::OcePluginAngularDeflection,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::OcePluginAngularDeflection,
&m_OcePluginAngularDeflection,
m_OcePluginAngularDeflection, 0.01, 360.0 ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::TriangulateSimplificationLevel,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::TriangulateSimplificationLevel,
&m_TriangulateSimplificationLevel,
m_TriangulateSimplificationLevel, 5, 1000 ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::TriangulateMinimumArea,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::TriangulateMinimumArea,
&m_TriangulateMinimumArea,
m_TriangulateMinimumArea, 25, 100000 ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableCacheFriendlyFracture,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::EnableCacheFriendlyFracture,
&m_EnableCacheFriendlyFracture,
m_EnableCacheFriendlyFracture ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::MaxFileSystemWatchers,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::MaxFileSystemWatchers,
&m_MaxFilesystemWatchers, m_MaxFilesystemWatchers,
0, 2147483647 ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::MinorSchematicGraphSize,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::MinorSchematicGraphSize,
&m_MinorSchematicGraphSize,
m_MinorSchematicGraphSize,
0, 2147483647 ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::ResolveTextRecursionDepth,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::ResolveTextRecursionDepth,
&m_ResolveTextRecursionDepth,
m_ResolveTextRecursionDepth, 0, 10 ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableExtensionSnaps,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::EnableExtensionSnaps,
&m_EnableExtensionSnaps,
m_EnableExtensionSnaps ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::ExtensionSnapTimeoutMs,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::ExtensionSnapTimeoutMs,
&m_ExtensionSnapTimeoutMs,
m_ExtensionSnapTimeoutMs, 0 ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ExtensionSnapActivateOnHover,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::ExtensionSnapActivateOnHover,
&m_ExtensionSnapActivateOnHover,
m_ExtensionSnapActivateOnHover ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableSnapAnchorsDebug,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::EnableSnapAnchorsDebug,
&m_EnableSnapAnchorsDebug,
m_EnableSnapAnchorsDebug ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::MinParallelAngle,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::MinParallelAngle,
&m_MinParallelAngle, m_MinParallelAngle,
0.0, 45.0 ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::HoleWallPaintingMultiplier,
m_entries.push_back( std::make_unique<PARAM_CFG_DOUBLE>( true, AC_KEYS::HoleWallPaintingMultiplier,
&m_HoleWallPaintingMultiplier,
m_HoleWallPaintingMultiplier,
0.1, 100.0 ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::MsgPanelShowUuids,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::MsgPanelShowUuids,
&m_MsgPanelShowUuids,
m_MsgPanelShowUuids ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::MaximumThreads,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::MaximumThreads,
&m_MaximumThreads, m_MaximumThreads,
0, 500 ) );
configParams.push_back(
new PARAM_CFG_INT( true, AC_KEYS::NetInspectorBulkUpdateOptimisationThreshold,
m_entries.push_back(
std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::NetInspectorBulkUpdateOptimisationThreshold,
&m_NetInspectorBulkUpdateOptimisationThreshold,
m_NetInspectorBulkUpdateOptimisationThreshold, 0, 1000 ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::ExcludeFromSimulationLineWidth,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::ExcludeFromSimulationLineWidth,
&m_ExcludeFromSimulationLineWidth,
m_ExcludeFromSimulationLineWidth, 1, 100 ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::GitIconRefreshInterval,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::GitIconRefreshInterval,
&m_GitIconRefreshInterval,
m_GitIconRefreshInterval, 0, 100000 ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::ConfigurableToolbars,
m_entries.push_back( std::make_unique<PARAM_CFG_BOOL>( true, AC_KEYS::ConfigurableToolbars,
&m_ConfigurableToolbars,
m_ConfigurableToolbars ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::MaxPastedTextLength,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::MaxPastedTextLength,
&m_MaxPastedTextLength,
m_MaxPastedTextLength, 0, 100000 ) );
configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::PNSProcessClusterTimeout,
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::PNSProcessClusterTimeout,
&m_PNSProcessClusterTimeout, 100, 10, 10000 ) );
// Special case for trace mask setting...we just grab them and set them immediately
// Because we even use wxLogTrace inside of advanced config
wxString traceMasks;
configParams.push_back( new PARAM_CFG_WXSTRING( true, AC_KEYS::TraceMasks, &traceMasks,
m_entries.push_back( std::make_unique<PARAM_CFG_WXSTRING>( true, AC_KEYS::TraceMasks, &m_traceMasks,
wxS( "" ) ) );
// Load the config from file
wxConfigLoadSetups( &aCfg, configParams );
wxConfigLoadSetups( &aCfg, m_entries );
// Now actually set the trace masks
wxStringTokenizer traceMaskTokenizer( traceMasks, wxS( "," ) );
wxStringTokenizer traceMaskTokenizer( m_traceMasks, wxS( "," ) );
while( traceMaskTokenizer.HasMoreTokens() )
{
@ -626,10 +639,7 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
wxLog::AddTraceMask( mask );
}
dumpCfg( configParams );
for( PARAM_CFG* param : configParams )
delete param;
dumpCfg( m_entries );
wxLogTrace( kicadTraceCoroutineStack, wxT( "Using coroutine stack size %d" ),
m_CoroutineStackSize );

View File

@ -30,12 +30,12 @@
#include <wx/config.h> // for wxConfigBase
#include <wx/debug.h> // for wxASSERT
void wxConfigLoadParams( wxConfigBase* aCfg, const std::vector<PARAM_CFG*>& aList,
void wxConfigLoadParams( wxConfigBase* aCfg, const std::vector<std::unique_ptr<PARAM_CFG>>& aList,
const wxString& aGroup )
{
wxASSERT( aCfg );
for( PARAM_CFG* param : aList )
for( const auto& param : aList )
{
if( !!param->m_Group )
aCfg->SetPath( param->m_Group );
@ -50,11 +50,11 @@ void wxConfigLoadParams( wxConfigBase* aCfg, const std::vector<PARAM_CFG*>& aLis
}
void wxConfigLoadSetups( wxConfigBase* aCfg, const std::vector<PARAM_CFG*>& aList )
void wxConfigLoadSetups( wxConfigBase* aCfg, const std::vector<std::unique_ptr<PARAM_CFG>>& aList )
{
wxASSERT( aCfg );
for( PARAM_CFG* param : aList )
for( const auto& param : aList )
{
if( !param->m_Setup )
continue;
@ -64,12 +64,12 @@ void wxConfigLoadSetups( wxConfigBase* aCfg, const std::vector<PARAM_CFG*>& aLis
}
void wxConfigSaveParams( wxConfigBase* aCfg, const std::vector<PARAM_CFG*>& aList,
void wxConfigSaveParams( wxConfigBase* aCfg, const std::vector<std::unique_ptr<PARAM_CFG>>& aList,
const wxString& aGroup )
{
wxASSERT( aCfg );
for( PARAM_CFG* param : aList )
for( const auto& param : aList )
{
if( !!param->m_Group )
aCfg->SetPath( param->m_Group );
@ -92,11 +92,11 @@ void wxConfigSaveParams( wxConfigBase* aCfg, const std::vector<PARAM_CFG*>& aLis
}
void wxConfigSaveSetups( wxConfigBase* aCfg, const std::vector<PARAM_CFG*>& aList )
void wxConfigSaveSetups( wxConfigBase* aCfg, const std::vector<std::unique_ptr<PARAM_CFG>>& aList )
{
wxASSERT( aCfg );
for( PARAM_CFG* param : aList )
for( const auto& param : aList )
{
if( !param->m_Setup )
continue;

View File

@ -24,8 +24,11 @@
#pragma once
#include <kicommon.h>
#include <memory>
#include <vector>
class wxConfigBase;
class PARAM_CFG;
/**
* @defgroup advanced_config Advanced Configuration Variables
@ -58,7 +61,7 @@ class wxConfigBase;
* config files, and why you might want to set them, see #AC_KEYS
*
*/
#include <wx/string.h>
class KICOMMON_API ADVANCED_CFG
{
public:
@ -70,6 +73,18 @@ public:
*/
static const ADVANCED_CFG& GetCfg();
/**
* Reload the configuration from the configuration file.
*/
void Reload();
/**
* Save the configuration to the configuration file.
*/
void Save();
const std::vector<std::unique_ptr<PARAM_CFG>>& GetEntries() const { return m_entries; }
///@{
/// \ingroup advanced_config
@ -766,6 +781,7 @@ public:
*/
int m_PNSProcessClusterTimeout;
wxString m_traceMasks; ///< Trace masks for wxLogTrace, loaded from the config file.
///@}
private:
@ -780,4 +796,6 @@ private:
* Load config from the given configuration base.
*/
void loadSettings( wxConfigBase& aCfg );
std::vector<std::unique_ptr<PARAM_CFG>> m_entries;
};

View File

@ -288,7 +288,7 @@ public:
* @param aCfg where to save.
* @param aList holds some configuration parameters, not all of which will necessarily be saved.
*/
KICOMMON_API void wxConfigSaveSetups( wxConfigBase* aCfg, const std::vector<PARAM_CFG*>& aList );
KICOMMON_API void wxConfigSaveSetups( wxConfigBase* aCfg, const std::vector<std::unique_ptr<PARAM_CFG>>& aList );
/**
* Write @a aList of #PARAM_CFG objects @a aCfg.
@ -300,7 +300,7 @@ KICOMMON_API void wxConfigSaveSetups( wxConfigBase* aCfg, const std::vector<PARA
* @param aGroup indicates in which group the value should be saved, unless the PARAM_CFG provides
* its own group, in which case it will take precedence. aGroup may be empty.
*/
KICOMMON_API void wxConfigSaveParams( wxConfigBase* aCfg, const std::vector<PARAM_CFG*>& aList,
KICOMMON_API void wxConfigSaveParams( wxConfigBase* aCfg, const std::vector<std::unique_ptr<PARAM_CFG>>& aList,
const wxString& aGroup );
/**
@ -311,7 +311,7 @@ KICOMMON_API void wxConfigSaveParams( wxConfigBase* aCfg, const std::vector<PARA
* @param aCfg where to load from.
* @param aList holds some configuration parameters, not all of which will necessarily be loaded.
*/
KICOMMON_API void wxConfigLoadSetups( wxConfigBase* aCfg, const std::vector<PARAM_CFG*>& aList );
KICOMMON_API void wxConfigLoadSetups( wxConfigBase* aCfg, const std::vector<std::unique_ptr<PARAM_CFG>>& aList );
/**
* Use @a aList of #PARAM_CFG objects to load configuration values from @a aCfg.
@ -322,7 +322,7 @@ KICOMMON_API void wxConfigLoadSetups( wxConfigBase* aCfg, const std::vector<PARA
* @param aGroup indicates in which group the value should be saved, unless the PARAM_CFG provides
* its own group, in which case it will take precedence. aGroup may be empty.
*/
KICOMMON_API void wxConfigLoadParams( wxConfigBase* aCfg, const std::vector<PARAM_CFG*>& aList,
KICOMMON_API void wxConfigLoadParams( wxConfigBase* aCfg, const std::vector<std::unique_ptr<PARAM_CFG>>& aList,
const wxString& aGroup );

View File

@ -29,6 +29,7 @@ set( KICAD_SRCS
dialogs/dialog_update_notice.cpp
dialogs/dialog_template_selector_base.cpp
dialogs/dialog_template_selector.cpp
dialogs/dialog_edit_cfg.cpp
dialogs/panel_kicad_launcher_base.cpp
dialogs/panel_kicad_launcher.cpp
dialogs/panel_jobset_base.cpp

View File

@ -0,0 +1,344 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dialog_edit_cfg.h"
#include <advanced_config.h>
#include <config_params.h>
#include <paths.h>
#include <wx/button.h>
#include <wx/display.h>
#include <wx/fileconf.h>
#include <wx/log.h>
#include <wx/menu.h>
#include <wx/sizer.h>
#include <wx/settings.h>
#include <functional>
#include <memory>
#include <set>
static wxString paramValueString( const PARAM_CFG& aParam )
{
wxString s;
try
{
switch( aParam.m_Type )
{
case paramcfg_id::PARAM_INT: s << *static_cast<const PARAM_CFG_INT&>( aParam ).m_Pt_param; break;
case paramcfg_id::PARAM_DOUBLE:
s = wxString::FromCDouble( *static_cast<const PARAM_CFG_DOUBLE&>( aParam ).m_Pt_param );
break;
case paramcfg_id::PARAM_WXSTRING: s = *static_cast<const PARAM_CFG_WXSTRING&>( aParam ).m_Pt_param; break;
case paramcfg_id::PARAM_BOOL:
s << ( *static_cast<const PARAM_CFG_BOOL&>( aParam ).m_Pt_param ? wxS( "true" ) : wxS( "false" ) );
break;
default:
wxLogError( wxS( "Unsupported PARAM_CFG variant: " ) + wxString::Format( wxS( "%d" ), aParam.m_Type ) );
}
}
catch( ... )
{
wxLogError( wxS( "Error converting parameter value to string." ) );
}
return s;
}
static wxString paramDefaultString( const PARAM_CFG& aParam )
{
wxString s;
try
{
switch( aParam.m_Type )
{
case paramcfg_id::PARAM_INT: s << static_cast<const PARAM_CFG_INT&>( aParam ).m_Default; break;
case paramcfg_id::PARAM_DOUBLE:
s = wxString::FromCDouble( static_cast<const PARAM_CFG_DOUBLE&>( aParam ).m_Default );
break;
case paramcfg_id::PARAM_WXSTRING: s << static_cast<const PARAM_CFG_WXSTRING&>( aParam ).m_default; break;
case paramcfg_id::PARAM_BOOL:
s << ( static_cast<const PARAM_CFG_BOOL&>( aParam ).m_Default ? wxS( "true" ) : wxS( "false" ) );
break;
default: break;
}
}
catch( ... )
{
wxLogError( wxS( "Error converting parameter default value to string." ) );
}
return s;
}
static void writeParam( PARAM_CFG& aParam, const wxString& aValue )
{
switch( aParam.m_Type )
{
case paramcfg_id::PARAM_INT:
{
PARAM_CFG_INT& param = static_cast<PARAM_CFG_INT&>( aParam );
*param.m_Pt_param = wxAtoi( aValue );
break;
}
case paramcfg_id::PARAM_BOOL:
{
PARAM_CFG_BOOL& param = static_cast<PARAM_CFG_BOOL&>( aParam );
if( aValue.CmpNoCase( wxS( "true" ) ) == 0 || aValue.CmpNoCase( wxS( "yes" ) ) == 0
|| aValue.CmpNoCase( wxS( "1" ) ) == 0 )
{
*param.m_Pt_param = true;
}
else
{
*param.m_Pt_param = false;
}
break;
}
case paramcfg_id::PARAM_DOUBLE:
{
PARAM_CFG_DOUBLE& param = static_cast<PARAM_CFG_DOUBLE&>( aParam );
aValue.ToCDouble( param.m_Pt_param );
break;
}
case paramcfg_id::PARAM_WXSTRING:
{
PARAM_CFG_WXSTRING& param = static_cast<PARAM_CFG_WXSTRING&>( aParam );
*param.m_Pt_param = aValue;
break;
}
default:
wxASSERT_MSG( false,
wxS( "Unsupported PARAM_CFG variant: " ) + wxString::Format( wxS( "%d" ), aParam.m_Type ) );
}
}
DIALOG_EDIT_CFG::DIALOG_EDIT_CFG( wxWindow* aParent ) :
wxDialog( aParent, wxID_ANY, _( "Edit Advanced Configuration" ), wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER )
{
m_cfgFile = wxFileName( PATHS::GetUserSettingsPath(), wxS( "kicad_advanced" ) );
m_grid = new wxGrid( this, wxID_ANY );
m_grid->CreateGrid( 0, 3 );
m_grid->SetColLabelValue( 0, _( "Key" ) );
m_grid->SetColLabelValue( 1, _( "Value" ) );
m_grid->SetColLabelValue( 2, _( "Extant" ) );
m_grid->HideCol( 2 );
m_grid->SetRowLabelSize( 0 );
loadSettings();
wxStdDialogButtonSizer* buttonSizer = new wxStdDialogButtonSizer();
wxButton* okButton = new wxButton( this, wxID_OK, _( "OK" ) );
okButton->SetDefault();
buttonSizer->AddButton( okButton );
buttonSizer->Realize();
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
sizer->Add( m_grid, 1, wxEXPAND | wxALL, 5 );
sizer->Add( buttonSizer, 0, wxEXPAND | wxALL, 5 );
SetSizer( sizer );
wxDisplay display( wxDisplay::GetFromWindow( this ) );
wxRect displayRect = display.GetClientArea();
SetMinSize( wxSize( 500, 300 ) );
SetMaxSize( wxSize( displayRect.GetWidth() - 100, displayRect.GetHeight() - 100 ) );
SetSizeHints( wxSize( 700, 500 ) );
m_grid->Bind( wxEVT_GRID_CELL_CHANGED, &DIALOG_EDIT_CFG::OnCellChange, this );
m_grid->Bind( wxEVT_GRID_CELL_RIGHT_CLICK, &DIALOG_EDIT_CFG::OnCellRightClick, this );
Bind( wxEVT_SIZE, &DIALOG_EDIT_CFG::OnSize, this );
m_contextRow = -1;
Layout();
Centre();
// CallAfter ensures layout is complete before column adjustment
CallAfter(
[this]()
{
adjustColumnWidths();
} );
}
void DIALOG_EDIT_CFG::adjustColumnWidths()
{
if( !m_grid || m_grid->GetNumberRows() == 0 )
return;
m_grid->Layout();
wxSize clientSize = m_grid->GetClientSize();
int availableWidth = clientSize.GetWidth();
// Reserve space for vertical scrollbar when we have many rows
availableWidth -= wxSystemSettings::GetMetric( wxSYS_VSCROLL_X );
if( availableWidth < 200 )
availableWidth = 200;
int keyWidth = ( availableWidth * 6 ) / 10;
int valueWidth = availableWidth - keyWidth;
keyWidth = std::max( keyWidth, 100 );
valueWidth = std::max( valueWidth, 80 );
m_grid->SetColSize( 0, keyWidth );
m_grid->SetColSize( 1, valueWidth );
// Prevent wxWidgets auto-sizing from interfering
m_grid->SetColMinimalAcceptableWidth( 50 );
}
void DIALOG_EDIT_CFG::OnSize( wxSizeEvent& aEvent )
{
aEvent.Skip();
if( m_grid && m_grid->GetNumberRows() > 0 )
{
// Defer column adjustment until resize is complete
CallAfter(
[this]()
{
adjustColumnWidths();
} );
}
}
void DIALOG_EDIT_CFG::loadSettings()
{
const ADVANCED_CFG& adv = ADVANCED_CFG::GetCfg();
const std::vector<std::unique_ptr<PARAM_CFG>>& entries = adv.GetEntries();
for( const auto& entry : entries )
{
wxString value = paramValueString( *entry );
wxString def = paramDefaultString( *entry );
int row = m_grid->GetNumberRows();
m_grid->AppendRows( 1 );
m_grid->SetCellValue( row, 0, entry->m_Ident );
m_grid->SetCellValue( row, 1, value );
m_grid->SetCellValue( row, 2, def == value ? wxS( "0" ) : wxS( "1" ) );
m_grid->SetReadOnly( row, 2 );
updateRowAppearance( row );
}
}
void DIALOG_EDIT_CFG::saveSettings()
{
int rows = m_grid->GetNumberRows();
for( int row = 0; row < rows; ++row )
{
wxString key = m_grid->GetCellValue( row, 0 );
wxString val = m_grid->GetCellValue( row, 1 );
wxString ext = m_grid->GetCellValue( row, 2 );
if( key.IsEmpty() || ext != wxS( "1" ) )
continue;
const std::vector<std::unique_ptr<PARAM_CFG>>& entries = ADVANCED_CFG::GetCfg().GetEntries();
for( auto& entry : entries )
{
if( entry->m_Ident == key )
{
writeParam( *entry, val );
break;
}
}
}
ADVANCED_CFG& adv = const_cast<ADVANCED_CFG&>( ADVANCED_CFG::GetCfg() );
adv.Save();
}
void DIALOG_EDIT_CFG::OnCellChange( wxGridEvent& aEvent )
{
int row = aEvent.GetRow();
int col = aEvent.GetCol();
if( col == 0 || col == 1 )
{
m_grid->SetCellValue( row, 2, wxS( "1" ) );
updateRowAppearance( row );
}
saveSettings();
int lastRow = m_grid->GetNumberRows() - 1;
if( !m_grid->GetCellValue( lastRow, 0 ).IsEmpty() || !m_grid->GetCellValue( lastRow, 1 ).IsEmpty() )
{
m_grid->AppendRows( 1 );
m_grid->SetCellValue( m_grid->GetNumberRows() - 1, 2, wxS( "0" ) );
m_grid->SetReadOnly( m_grid->GetNumberRows() - 1, 2 );
updateRowAppearance( m_grid->GetNumberRows() - 1 );
}
aEvent.Skip();
}
void DIALOG_EDIT_CFG::OnCellRightClick( wxGridEvent& aEvent )
{
m_contextRow = aEvent.GetRow();
wxMenu menu;
menu.Append( wxID_ANY, _( "Reset to default" ) );
menu.Bind( wxEVT_MENU, &DIALOG_EDIT_CFG::OnResetDefault, this );
PopupMenu( &menu );
menu.Unbind( wxEVT_MENU, &DIALOG_EDIT_CFG::OnResetDefault, this );
}
void DIALOG_EDIT_CFG::OnResetDefault( wxCommandEvent& aEvent )
{
if( m_contextRow < 0 )
return;
wxString key = m_grid->GetCellValue( m_contextRow, 0 );
wxString def;
const ADVANCED_CFG& adv = ADVANCED_CFG::GetCfg();
const std::vector<std::unique_ptr<PARAM_CFG>>& entries = adv.GetEntries();
for( const auto& entry : entries )
{
if( entry->m_Ident == key )
{
def = paramDefaultString( *entry );
break;
}
}
m_grid->SetCellValue( m_contextRow, 1, def );
m_grid->SetCellValue( m_contextRow, 2, wxS( "0" ) );
updateRowAppearance( m_contextRow );
saveSettings();
}
void DIALOG_EDIT_CFG::updateRowAppearance( int aRow )
{
bool ext = m_grid->GetCellValue( aRow, 2 ) == wxS( "1" );
wxFont font = m_grid->GetCellFont( aRow, 0 );
font.SetWeight( ext ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL );
m_grid->SetCellFont( aRow, 0, font );
m_grid->SetCellFont( aRow, 1, font );
}

View File

@ -0,0 +1,44 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <wx/dialog.h>
#include <wx/grid.h>
#include <wx/filename.h>
class DIALOG_EDIT_CFG : public wxDialog
{
public:
DIALOG_EDIT_CFG( wxWindow* aParent );
private:
void adjustColumnWidths();
void OnSize( wxSizeEvent& aEvent );
void loadSettings();
void saveSettings();
void OnCellChange( wxGridEvent& aEvent );
void OnCellRightClick( wxGridEvent& aEvent );
void OnResetDefault( wxCommandEvent& aEvent );
void updateRowAppearance( int aRow );
wxGrid* m_grid;
wxFileName m_cfgFile;
int m_contextRow;
};

View File

@ -35,6 +35,7 @@ enum id_kicad_frm {
ID_LEFT_FRAME = ID_KICAD_MANAGER_START,
ID_PROJECT_TREE,
ID_EDIT_LOCAL_FILE_IN_TEXT_EDITOR,
ID_EDIT_ADVANCED_CFG,
ID_IMPORT_CADSTAR_ARCHIVE_PROJECT,
ID_IMPORT_EAGLE_PROJECT,
ID_IMPORT_EASYEDA_PROJECT,

View File

@ -37,6 +37,7 @@
#include <dialogs/panel_kicad_launcher.h>
#include <dialogs/dialog_update_check_prompt.h>
#include <dialogs/panel_jobset.h>
#include <dialogs/dialog_edit_cfg.h>
#include <eda_base_frame.h>
#include <executable_names.h>
#include <file_history.h>
@ -106,6 +107,7 @@ BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME )
// Menu events
EVT_MENU( wxID_EXIT, KICAD_MANAGER_FRAME::OnExit )
EVT_MENU( ID_EDIT_LOCAL_FILE_IN_TEXT_EDITOR, KICAD_MANAGER_FRAME::OnOpenFileInTextEditor )
EVT_MENU( ID_EDIT_ADVANCED_CFG, KICAD_MANAGER_FRAME::OnEditAdvancedCfg )
EVT_MENU( ID_IMPORT_CADSTAR_ARCHIVE_PROJECT, KICAD_MANAGER_FRAME::OnImportCadstarArchiveFiles )
EVT_MENU( ID_IMPORT_EAGLE_PROJECT, KICAD_MANAGER_FRAME::OnImportEagleFiles )
EVT_MENU( ID_IMPORT_EASYEDA_PROJECT, KICAD_MANAGER_FRAME::OnImportEasyEdaFiles )
@ -971,6 +973,13 @@ void KICAD_MANAGER_FRAME::OnOpenFileInTextEditor( wxCommandEvent& event )
}
void KICAD_MANAGER_FRAME::OnEditAdvancedCfg( wxCommandEvent& WXUNUSED( event ) )
{
DIALOG_EDIT_CFG dlg( this );
dlg.ShowModal();
}
void KICAD_MANAGER_FRAME::RefreshProjectTree()
{
m_leftWin->ReCreateTreePrj();

View File

@ -57,6 +57,7 @@ public:
void UnarchiveFiles();
void OnOpenFileInTextEditor( wxCommandEvent& event );
void OnEditAdvancedCfg( wxCommandEvent& event );
void OnFileHistory( wxCommandEvent& event );
void OnClearFileHistory( wxCommandEvent& aEvent );

View File

@ -40,6 +40,7 @@
#include "kicad_id.h"
#include <widgets/wx_menubar.h>
#include <wx/dir.h>
#include <wx/utils.h>
void KICAD_MANAGER_FRAME::doReCreateMenuBar()
@ -153,6 +154,15 @@ void KICAD_MANAGER_FRAME::doReCreateMenuBar()
editMenu->Add( ACTIONS::copy );
editMenu->Add( ACTIONS::paste );
wxString editCfgEnv;
if( wxGetEnv( wxS( "KICAD_EDIT_ADVANCED_CFG" ), &editCfgEnv ); editCfgEnv == wxS( "1" ) )
{
editMenu->Add( _( "Edit Advanced Config..." ),
_( "Edit advanced settings" ),
ID_EDIT_ADVANCED_CFG,
BITMAPS::editor );
}
//-- View menu -----------------------------------------------------------
//
ACTION_MENU* viewMenu = new ACTION_MENU( false, controlTool );