diff --git a/common/project/project_local_settings.cpp b/common/project/project_local_settings.cpp index 0766f0004f..7c48ed3c66 100644 --- a/common/project/project_local_settings.cpp +++ b/common/project/project_local_settings.cpp @@ -29,7 +29,8 @@ 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_project( nullptr ), + m_SelectionFilter() { m_params.emplace_back( new PARAM_LAMBDA( "board.visible_layers", [&]() -> std::string @@ -80,6 +81,63 @@ PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( const std::string& aFilename ) : } }, {} ) ); + + m_params.emplace_back( new PARAM_LAMBDA( "board.selection_filter", + [&]() -> nlohmann::json + { + nlohmann::json ret; + + ret["lockedItems"] = m_SelectionFilter.lockedItems; + ret["footprints"] = m_SelectionFilter.footprints; + ret["text"] = m_SelectionFilter.text; + ret["tracks"] = m_SelectionFilter.tracks; + ret["vias"] = m_SelectionFilter.vias; + ret["pads"] = m_SelectionFilter.pads; + ret["graphics"] = m_SelectionFilter.graphics; + ret["zones"] = m_SelectionFilter.zones; + ret["keepouts"] = m_SelectionFilter.keepouts; + ret["dimensions"] = m_SelectionFilter.dimensions; + ret["otherItems"] = m_SelectionFilter.otherItems; + + return ret; + }, + [&]( const nlohmann::json& aVal ) + { + if( aVal.empty() || !aVal.is_object() ) + return; + + auto setIfPresent = + [&aVal]( const std::string& aKey, bool& aTarget ) + { + if( aVal.contains( aKey ) && aVal.at( aKey ).is_boolean() ) + aTarget = aVal.at( aKey ).get(); + }; + + setIfPresent( "lockedItems", m_SelectionFilter.lockedItems ); + setIfPresent( "footprints", m_SelectionFilter.footprints ); + setIfPresent( "text", m_SelectionFilter.text ); + setIfPresent( "tracks", m_SelectionFilter.tracks ); + setIfPresent( "vias", m_SelectionFilter.vias ); + setIfPresent( "pads", m_SelectionFilter.pads ); + setIfPresent( "graphics", m_SelectionFilter.graphics ); + setIfPresent( "zones", m_SelectionFilter.zones ); + setIfPresent( "keepouts", m_SelectionFilter.keepouts ); + setIfPresent( "dimensions", m_SelectionFilter.dimensions ); + setIfPresent( "otherItems", m_SelectionFilter.otherItems ); + }, + { + { "lockedItems", true }, + { "footprints", true }, + { "text", true }, + { "tracks", true }, + { "vias", true }, + { "pads", true }, + { "graphics", true }, + { "zones", true }, + { "keepouts", true }, + { "dimensions", true }, + { "otherItems", true } + } ) ); } diff --git a/include/project/board_local_settings.h b/include/project/board_local_settings.h new file mode 100644 index 0000000000..e05220a8ba --- /dev/null +++ b/include/project/board_local_settings.h @@ -0,0 +1,70 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2020 Jon Evans + * Copyright (C) 2020 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 . + */ + +#ifndef KICAD_BOARD_LOCAL_SETTINGS_H +#define KICAD_BOARD_LOCAL_SETTINGS_H + +/** + * Selection filtering that applies all the time (not the "filter selection" dialog that modifies + * the current selection) + */ +struct SELECTION_FILTER_OPTIONS +{ + bool lockedItems; ///< Allow selecting locked items + bool footprints; ///< Allow selecting entire footprints + bool text; ///< Text (free or attached to a footprint) + bool tracks; ///< Copper tracks + bool vias; ///< Vias (all types> + bool pads; ///< Footprint pads + bool graphics; ///< Graphic lines, shapes, polygons + bool zones; ///< Copper zones + bool keepouts; ///< Keepout zones + bool dimensions; ///< Dimension items + bool otherItems; ///< Anything not fitting one of the above categories + + SELECTION_FILTER_OPTIONS() + { + lockedItems = true; + footprints = true; + text = true; + tracks = true; + vias = true; + pads = true; + graphics = true; + zones = true; + keepouts = true; + dimensions = true; + otherItems = true; + } + + bool Any() + { + return ( lockedItems || footprints || text || tracks || vias || pads || graphics || zones + || keepouts || dimensions || otherItems ); + } + + bool All() + { + return ( lockedItems && footprints && text && tracks && vias && pads && graphics && zones + && keepouts && dimensions && otherItems ); + } +}; + +#endif // KICAD_BOARD_LOCAL_SETTINGS_H diff --git a/include/project/project_local_settings.h b/include/project/project_local_settings.h index 0fca124b65..e8c9338a96 100644 --- a/include/project/project_local_settings.h +++ b/include/project/project_local_settings.h @@ -22,6 +22,7 @@ #define KICAD_PROJECT_LOCAL_SETTINGS_H #include +#include #include #include @@ -83,6 +84,9 @@ public: /// The GAL layers (aka items) that are turned on for viewing (@see GAL_LAYER_ID) GAL_SET m_VisibleItems; + + /// State of the selection filter widget + SELECTION_FILTER_OPTIONS m_SelectionFilter; }; #endif diff --git a/pcbnew/pcbnew_config.cpp b/pcbnew/pcbnew_config.cpp index 5d7f7b3fd3..780153a77e 100644 --- a/pcbnew/pcbnew_config.cpp +++ b/pcbnew/pcbnew_config.cpp @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include #include @@ -46,7 +48,9 @@ #include #include #include +#include #include +#include void PCB_EDIT_FRAME::On3DShapeLibWizard( wxCommandEvent& event ) @@ -91,6 +95,13 @@ bool PCB_EDIT_FRAME::LoadProjectSettings() pglayout.SetPageLayout( filename ); + PROJECT_LOCAL_SETTINGS& localSettings = Prj().GetLocalSettings(); + + SELECTION_FILTER_OPTIONS& filterOpts = GetToolManager()->GetTool()->GetFilter(); + + filterOpts = localSettings.m_SelectionFilter; + m_selectionFilterPanel->SetCheckboxesFromFilter( filterOpts ); + return true; } @@ -115,5 +126,11 @@ void PCB_EDIT_FRAME::SaveProjectSettings() RecordDRCExclusions(); + PROJECT_LOCAL_SETTINGS& localSettings = Prj().GetLocalSettings(); + + SELECTION_FILTER_OPTIONS& filterOpts = GetToolManager()->GetTool()->GetFilter(); + + localSettings.m_SelectionFilter = filterOpts; + GetSettingsManager()->SaveProject(); } diff --git a/pcbnew/tools/selection_tool.h b/pcbnew/tools/selection_tool.h index d2cd81780f..85f1cb34ea 100644 --- a/pcbnew/tools/selection_tool.h +++ b/pcbnew/tools/selection_tool.h @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -49,26 +50,6 @@ namespace KIGFX typedef void (*CLIENT_SELECTION_FILTER)( const VECTOR2I&, GENERAL_COLLECTOR& ); -/** - * Selection filtering that applies all the time (not the "filter selection" dialog that modifies - * the current selection) - */ -struct SELECTION_FILTER_OPTIONS -{ - bool lockedItems; ///< Allow selecting locked items - bool footprints; ///< Allow selecting entire footprints - bool text; ///< Text (free or attached to a footprint) - bool tracks; ///< Copper tracks - bool vias; ///< Vias (all types> - bool pads; ///< Footprint pads - bool graphics; ///< Graphic lines, shapes, polygons - bool zones; ///< Copper zones - bool keepouts; ///< Keepout zones - bool dimensions; ///< Dimension items - bool otherItems; ///< Anything not fitting one of the above categories -}; - - /** * SELECTION_TOOL * diff --git a/pcbnew/widgets/panel_selection_filter.cpp b/pcbnew/widgets/panel_selection_filter.cpp index 45d85f4b55..8c6d81d104 100644 --- a/pcbnew/widgets/panel_selection_filter.cpp +++ b/pcbnew/widgets/panel_selection_filter.cpp @@ -33,10 +33,8 @@ PANEL_SELECTION_FILTER::PANEL_SELECTION_FILTER( wxWindow* aParent ) : m_tool = m_frame->GetToolManager()->GetTool(); wxASSERT( m_tool ); - m_cbAllItems->SetValue( true ); - - wxCommandEvent dummy; - OnFilterChanged( dummy ); + SELECTION_FILTER_OPTIONS& opts = m_tool->GetFilter(); + SetCheckboxesFromFilter( opts ); m_cbFootprints->Bind( wxEVT_RIGHT_DOWN, &PANEL_SELECTION_FILTER::onRightClick, this ); m_cbText->Bind( wxEVT_RIGHT_DOWN, &PANEL_SELECTION_FILTER::onRightClick, this ); @@ -51,6 +49,28 @@ PANEL_SELECTION_FILTER::PANEL_SELECTION_FILTER( wxWindow* aParent ) : } +void PANEL_SELECTION_FILTER::SetCheckboxesFromFilter( SELECTION_FILTER_OPTIONS& aOptions ) +{ + Freeze(); + + m_cbLockedItems->SetValue( aOptions.lockedItems ); + m_cbFootprints->SetValue( aOptions.footprints ); + m_cbText->SetValue( aOptions.text ); + m_cbTracks->SetValue( aOptions.tracks ); + m_cbVias->SetValue( aOptions.vias ); + m_cbPads->SetValue( aOptions.pads ); + m_cbGraphics->SetValue( aOptions.graphics ); + m_cbZones->SetValue( aOptions.zones ); + m_cbKeepouts->SetValue( aOptions.keepouts ); + m_cbDimensions->SetValue( aOptions.dimensions ); + m_cbOtherItems->SetValue( aOptions.otherItems ); + + m_cbAllItems->SetValue( aOptions.All() ); + + Thaw(); +} + + void PANEL_SELECTION_FILTER::OnFilterChanged( wxCommandEvent& aEvent ) { if( aEvent.GetEventObject() == m_cbAllItems ) @@ -92,9 +112,7 @@ bool PANEL_SELECTION_FILTER::setFilterFromCheckboxes( SELECTION_FILTER_OPTIONS& aOptions.dimensions = m_cbDimensions->GetValue(); aOptions.otherItems = m_cbOtherItems->GetValue(); - return ( aOptions.lockedItems && aOptions.footprints && aOptions.text && aOptions.tracks - && aOptions.vias && aOptions.pads && aOptions.graphics && aOptions.zones - && aOptions.keepouts && aOptions.dimensions && aOptions.otherItems ); + return aOptions.All(); } diff --git a/pcbnew/widgets/panel_selection_filter.h b/pcbnew/widgets/panel_selection_filter.h index 784d833ca8..b08f685530 100644 --- a/pcbnew/widgets/panel_selection_filter.h +++ b/pcbnew/widgets/panel_selection_filter.h @@ -35,6 +35,8 @@ public: ~PANEL_SELECTION_FILTER() = default; + void SetCheckboxesFromFilter( SELECTION_FILTER_OPTIONS& aOptions ); + protected: void OnFilterChanged( wxCommandEvent& aEvent ) override;