From 300d92438c5373c1e8e2ee5e2a0961bb365b08ef Mon Sep 17 00:00:00 2001
From: Jon Evans <jon@craftyjon.com>
Date: Fri, 26 Aug 2022 20:18:16 -0400
Subject: [PATCH] Allow hiding symbol library tables from symbol chooser

Hidden but loaded libraries are useful when using database libraries
---
 common/lib_table.keywords                | 3 ++-
 common/lib_table_base.cpp                | 6 +++++-
 common/lib_tree_model.cpp                | 2 +-
 eeschema/dialogs/panel_sym_lib_table.cpp | 5 +++++
 eeschema/picksymbol.cpp                  | 3 ++-
 eeschema/symbol_lib_table.cpp            | 8 ++++++++
 eeschema/symbol_tree_model_adapter.cpp   | 3 +++
 include/lib_table_base.h                 | 8 ++++++++
 include/lib_table_grid.h                 | 8 ++++++++
 pcbnew/dialogs/panel_fp_lib_table.cpp    | 5 +++++
 10 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/common/lib_table.keywords b/common/lib_table.keywords
index fd679ffa61..8de5aef791 100644
--- a/common/lib_table.keywords
+++ b/common/lib_table.keywords
@@ -6,4 +6,5 @@ type
 uri
 options
 descr
-disabled
\ No newline at end of file
+disabled
+hidden
\ No newline at end of file
diff --git a/common/lib_table_base.cpp b/common/lib_table_base.cpp
index 524c473473..f660263fcf 100644
--- a/common/lib_table_base.cpp
+++ b/common/lib_table_base.cpp
@@ -89,6 +89,9 @@ void LIB_TABLE_ROW::Format( OUTPUTFORMATTER* out, int nestLevel ) const
     if( !GetIsEnabled() )
         extraOptions += "(disabled)";
 
+    if( !GetIsVisible() )
+        extraOptions += "(hidden)";
+
     out->Print( nestLevel, "(lib (name %s)(type %s)(uri %s)(options %s)(descr %s)%s)\n",
                 out->Quotew( GetNickName() ).c_str(),
                 out->Quotew( GetType() ).c_str(),
@@ -105,7 +108,8 @@ bool LIB_TABLE_ROW::operator==( const LIB_TABLE_ROW& r ) const
         && uri_user == r.uri_user
         && options == r.options
         && description == r.description
-        && enabled == r.enabled;
+        && enabled == r.enabled
+        && visible == r.visible;
 }
 
 
diff --git a/common/lib_tree_model.cpp b/common/lib_tree_model.cpp
index 395a29955f..6c8f64e4b0 100644
--- a/common/lib_tree_model.cpp
+++ b/common/lib_tree_model.cpp
@@ -1,6 +1,6 @@
 /*
  * This program source code file is part of KiCad, a free EDA CAD application.
- *
+ *lib_tree_model
  * Copyright (C) 2017 Chris Pavlina <pavlina.chris@gmail.com>
  * Copyright (C) 2014 Henner Zeller <h.zeller@acm.org>
  * Copyright (C) 2014-2019 KiCad Developers, see AUTHORS.txt for contributors.
diff --git a/eeschema/dialogs/panel_sym_lib_table.cpp b/eeschema/dialogs/panel_sym_lib_table.cpp
index f6fb58fcff..513bb4a30b 100644
--- a/eeschema/dialogs/panel_sym_lib_table.cpp
+++ b/eeschema/dialogs/panel_sym_lib_table.cpp
@@ -257,6 +257,11 @@ PANEL_SYM_LIB_TABLE::PANEL_SYM_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent, P
                 attr->SetReadOnly();    // not really; we delegate interactivity to GRID_TRICKS
                 aGrid->SetColAttr( COL_ENABLED, attr );
 
+                attr = new wxGridCellAttr;
+                attr->SetRenderer( new wxGridCellBoolRenderer() );
+                attr->SetReadOnly();    // not really; we delegate interactivity to GRID_TRICKS
+                aGrid->SetColAttr( COL_VISIBLE, attr );
+
                 // all but COL_OPTIONS, which is edited with Option Editor anyways.
                 aGrid->AutoSizeColumn( COL_NICKNAME, false );
                 aGrid->AutoSizeColumn( COL_TYPE, false );
diff --git a/eeschema/picksymbol.cpp b/eeschema/picksymbol.cpp
index fe033e37ff..cdccfad499 100644
--- a/eeschema/picksymbol.cpp
+++ b/eeschema/picksymbol.cpp
@@ -129,7 +129,8 @@ PICKED_SYMBOL SCH_BASE_FRAME::PickSymbolFromLibTree( const SYMBOL_LIBRARY_FILTER
                 bool pinned = alg::contains( cfg->m_Session.pinned_symbol_libs, nickname )
                                 || alg::contains( project.m_PinnedSymbolLibs, nickname );
 
-                modelAdapter->AddLibrary( nickname, pinned );
+                if( libs->FindRow( nickname )->GetIsVisible() )
+                    modelAdapter->AddLibrary( nickname, pinned );
             }
         }
 
diff --git a/eeschema/symbol_lib_table.cpp b/eeschema/symbol_lib_table.cpp
index fe5553e7b7..27cfc17d13 100644
--- a/eeschema/symbol_lib_table.cpp
+++ b/eeschema/symbol_lib_table.cpp
@@ -150,6 +150,7 @@ void SYMBOL_LIB_TABLE::Parse( LIB_TABLE_LEXER* in )
         bool    sawDesc     = false;
         bool    sawUri      = false;
         bool    sawDisabled = false;
+        bool    sawHidden   = false;
 
         while( ( tok = in->NextTok() ) != T_RIGHT )
         {
@@ -202,6 +203,13 @@ void SYMBOL_LIB_TABLE::Parse( LIB_TABLE_LEXER* in )
                 row->SetEnabled( false );
                 break;
 
+            case T_hidden:
+                if( sawHidden )
+                    in->Duplicate( tok );
+                sawHidden = true;
+                row->SetVisible( false );
+                break;
+
             default:
                 in->Unexpected( tok );
             }
diff --git a/eeschema/symbol_tree_model_adapter.cpp b/eeschema/symbol_tree_model_adapter.cpp
index aa7c585094..20667bb597 100644
--- a/eeschema/symbol_tree_model_adapter.cpp
+++ b/eeschema/symbol_tree_model_adapter.cpp
@@ -120,6 +120,9 @@ bool SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector<wxString>& aNick
 
         for( const std::pair<const wxString, std::vector<LIB_SYMBOL*>>& pair : loadedSymbols )
         {
+            if( !m_libs->FindRow( pair.first )->GetIsVisible() )
+                continue;
+
             std::vector<LIB_TREE_ITEM*> treeItems( pair.second.begin(), pair.second.end() );
             bool pinned = alg::contains( cfg->m_Session.pinned_symbol_libs, pair.first )
                             || alg::contains( project.m_PinnedSymbolLibs, pair.first );
diff --git a/include/lib_table_base.h b/include/lib_table_base.h
index a2910b985b..3cb96feca8 100644
--- a/include/lib_table_base.h
+++ b/include/lib_table_base.h
@@ -69,6 +69,7 @@ class LIB_TABLE_ROW : boost::noncopyable
 public:
     LIB_TABLE_ROW() :
         enabled( true ),
+        visible( true ),
         m_loaded( false ),
         m_parent( nullptr )
     {
@@ -83,6 +84,7 @@ public:
         nickName( aNick ),
         description( aDescr ),
         enabled( true ),
+        visible( true ),
         m_loaded( false ),
         m_parent( aParent )
     {
@@ -125,6 +127,10 @@ public:
      */
     void SetEnabled( bool aEnabled = true ) { enabled = aEnabled; }
 
+    bool GetIsVisible() const { return visible; }
+
+    void SetVisible( bool aVisible = true ) { visible = aVisible; }
+
     /**
      * Return the type of library represented by this row.
      */
@@ -205,6 +211,7 @@ protected:
         options( aRow.options ),
         description( aRow.description ),
         enabled( aRow.enabled ),
+        visible( aRow.visible ),
         m_loaded( aRow.m_loaded ),
         m_parent( aRow.m_parent )
     {
@@ -232,6 +239,7 @@ private:
     wxString          description;
 
     bool              enabled  = true;    ///< Whether the LIB_TABLE_ROW is enabled
+    bool              visible  = true;    ///< Whether the LIB_TABLE_ROW is visible in choosers
     bool              m_loaded = false;   ///< Whether the LIB_TABLE_ROW is loaded
     LIB_TABLE*        m_parent;           ///< Pointer to the table this row lives in (maybe null)
 
diff --git a/include/lib_table_grid.h b/include/lib_table_grid.h
index d7e6f49549..e2e498b708 100644
--- a/include/lib_table_grid.h
+++ b/include/lib_table_grid.h
@@ -31,6 +31,7 @@ const wxColour COLOUR_ROW_DISABLED( 100, 100, 100 );
 enum COL_ORDER
 {
     COL_ENABLED,
+    COL_VISIBLE,
     COL_NICKNAME,
     COL_URI,
     COL_TYPE,
@@ -68,6 +69,7 @@ public:
             case COL_OPTIONS:  return r->GetOptions();
             case COL_DESCR:    return r->GetDescr();
             case COL_ENABLED:  return r->GetIsEnabled() ? wxT( "1" ) : wxT( "0" );
+            case COL_VISIBLE:  return r->GetIsVisible() ? wxT( "1" ) : wxT( "0" );
             default:           return wxEmptyString;
             }
         }
@@ -79,6 +81,8 @@ public:
     {
         if( aRow < (int) size() && aCol == COL_ENABLED )
             return at( (size_t) aRow )->GetIsEnabled();
+        else if( aRow < (int) size() && aCol == COL_VISIBLE )
+            return at( (size_t) aRow )->GetIsVisible();
         else
             return false;
     }
@@ -97,6 +101,7 @@ public:
             case COL_OPTIONS:  r->SetOptions( aValue );                             break;
             case COL_DESCR:    r->SetDescr( aValue );                               break;
             case COL_ENABLED:  r->SetEnabled( aValue == wxT( "1" ) );               break;
+            case COL_VISIBLE:  r->SetVisible( aValue == wxT( "1" ) );               break;
             }
         }
     }
@@ -105,6 +110,8 @@ public:
     {
         if( aRow < (int) size() && aCol == COL_ENABLED )
             at( (size_t) aRow )->SetEnabled( aValue );
+        else if( aRow < (int) size() && aCol == COL_VISIBLE )
+            at( (size_t) aRow )->SetVisible( aValue );
     }
 
     bool IsEmptyCell( int aRow, int aCol ) override
@@ -184,6 +191,7 @@ public:
         case COL_OPTIONS:   return _( "Options" );
         case COL_DESCR:     return _( "Description" );
         case COL_ENABLED:   return _( "Active" );
+        case COL_VISIBLE:   return _( "Visible" );
 
         default:            return wxEmptyString;
         }
diff --git a/pcbnew/dialogs/panel_fp_lib_table.cpp b/pcbnew/dialogs/panel_fp_lib_table.cpp
index 0f2c193e62..dd6dbf0879 100644
--- a/pcbnew/dialogs/panel_fp_lib_table.cpp
+++ b/pcbnew/dialogs/panel_fp_lib_table.cpp
@@ -419,6 +419,11 @@ PANEL_FP_LIB_TABLE::PANEL_FP_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent,
                 attr->SetReadOnly();    // not really; we delegate interactivity to GRID_TRICKS
                 aGrid->SetColAttr( COL_ENABLED, attr );
 
+                // No visibility control for footprint libraries yet; this feature is primarily
+                // useful for database libraries and it's only implemented for schematic symbols
+                // at the moment.
+                aGrid->HideCol( COL_VISIBLE );
+
                 // all but COL_OPTIONS, which is edited with Option Editor anyways.
                 aGrid->AutoSizeColumn( COL_NICKNAME, false );
                 aGrid->AutoSizeColumn( COL_TYPE, false );