You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

227 lines
7.3 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2020 CERN
  5. * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software: you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the
  9. * Free Software Foundation, either version 3 of the License, or (at your
  10. * option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <core/kicad_algo.h>
  21. #include <dialog_update_symbol_fields.h>
  22. #include <lib_symbol.h>
  23. #include <symbol_edit_frame.h>
  24. #include <sch_commit.h>
  25. #include <template_fieldnames.h>
  26. #include <string_utils.h>
  27. bool g_removeExtraLibFields = false;
  28. bool g_resetEmptyLibFields = false;
  29. bool g_resetLibFieldText = true;
  30. bool g_resetLibFieldVisibilities = true;
  31. bool g_resetLibFieldEffects = true;
  32. bool g_resetLibFieldPositions = true;
  33. DIALOG_UPDATE_SYMBOL_FIELDS::DIALOG_UPDATE_SYMBOL_FIELDS( SYMBOL_EDIT_FRAME* aParent,
  34. LIB_SYMBOL* aSymbol ) :
  35. DIALOG_UPDATE_SYMBOL_FIELDS_BASE( aParent ),
  36. m_editFrame( aParent ),
  37. m_symbol( aSymbol)
  38. {
  39. wxASSERT( aParent );
  40. wxASSERT( aSymbol );
  41. m_parentSymbolReadOnly->SetValue( UnescapeString( m_symbol->GetParent().lock()->GetName() ) );
  42. for( int i = 0; i < MANDATORY_FIELDS; ++i )
  43. {
  44. m_fieldsBox->Append( TEMPLATE_FIELDNAME::GetDefaultFieldName( i, DO_TRANSLATE ) );
  45. m_fieldsBox->Check( i, true );
  46. }
  47. updateFieldsList();
  48. m_removeExtraBox->SetValue( g_removeExtraLibFields );
  49. m_resetEmptyFields->SetValue( g_resetEmptyLibFields );
  50. m_resetFieldText->SetValue( g_resetLibFieldText );
  51. m_resetFieldVisibilities->SetValue( g_resetLibFieldVisibilities );
  52. m_resetFieldEffects->SetValue( g_resetLibFieldEffects );
  53. m_resetFieldPositions->SetValue( g_resetLibFieldPositions );
  54. SetupStandardButtons();
  55. // Now all widgets have the size fixed, call FinishDialogSettings
  56. finishDialogSettings();
  57. }
  58. DIALOG_UPDATE_SYMBOL_FIELDS::~DIALOG_UPDATE_SYMBOL_FIELDS()
  59. {
  60. g_removeExtraLibFields = m_removeExtraBox->GetValue();
  61. g_resetEmptyLibFields = m_resetEmptyFields->GetValue();
  62. g_resetLibFieldText = m_resetFieldText->GetValue();
  63. g_resetLibFieldVisibilities = m_resetFieldVisibilities->GetValue();
  64. g_resetLibFieldEffects = m_resetFieldEffects->GetValue();
  65. g_resetLibFieldPositions = m_resetFieldPositions->GetValue();
  66. }
  67. void DIALOG_UPDATE_SYMBOL_FIELDS::updateFieldsList()
  68. {
  69. // Load non-mandatory fields from the parent part
  70. std::vector<LIB_FIELD*> libFields;
  71. std::set<wxString> fieldNames;
  72. std::unique_ptr<LIB_SYMBOL> flattenedParent = m_symbol->GetParent().lock()->Flatten();
  73. flattenedParent->GetFields( libFields );
  74. for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
  75. fieldNames.insert( libFields[i]->GetName() );
  76. libFields.clear(); // flattenedPart is about to go out of scope...
  77. // Load non-mandatory fields from the editor symbol
  78. m_symbol->GetFields( libFields );
  79. for( unsigned i = MANDATORY_FIELDS; i < libFields.size(); ++i )
  80. fieldNames.insert( libFields[i]->GetName() );
  81. libFields.clear();
  82. // Update the listbox widget
  83. for( unsigned i = m_fieldsBox->GetCount() - 1; i >= MANDATORY_FIELDS; --i )
  84. m_fieldsBox->Delete( i );
  85. for( const wxString& fieldName : fieldNames )
  86. m_fieldsBox->Append( fieldName );
  87. for( unsigned i = MANDATORY_FIELDS; i < m_fieldsBox->GetCount(); ++i )
  88. m_fieldsBox->Check( i, true );
  89. }
  90. void DIALOG_UPDATE_SYMBOL_FIELDS::checkAll( bool aCheck )
  91. {
  92. for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
  93. m_fieldsBox->Check( i, aCheck );
  94. }
  95. void DIALOG_UPDATE_SYMBOL_FIELDS::onOkButtonClicked( wxCommandEvent& aEvent )
  96. {
  97. wxBusyCursor dummy;
  98. SCH_COMMIT commit( m_editFrame );
  99. commit.Modify( m_symbol );
  100. // Create the set of fields to be updated
  101. m_updateFields.clear();
  102. for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
  103. {
  104. if( m_fieldsBox->IsChecked( i ) )
  105. m_updateFields.insert( m_fieldsBox->GetString( i ) );
  106. }
  107. std::unique_ptr<LIB_SYMBOL> flattenedParent = m_symbol->GetParent().lock()->Flatten();
  108. bool removeExtras = m_removeExtraBox->GetValue();
  109. bool resetVis = m_resetFieldVisibilities->GetValue();
  110. bool resetEffects = m_resetFieldEffects->GetValue();
  111. bool resetPositions = m_resetFieldPositions->GetValue();
  112. std::vector<LIB_FIELD> fields;
  113. std::vector<LIB_FIELD> result;
  114. m_symbol->GetFields( fields );
  115. for( LIB_FIELD& field : fields )
  116. {
  117. bool copy = true;
  118. LIB_FIELD* parentField = nullptr;
  119. if( alg::contains( m_updateFields, field.GetName() ) )
  120. {
  121. parentField = flattenedParent->FindField( field.GetName() );
  122. if( parentField )
  123. {
  124. bool resetText = parentField->GetText().IsEmpty() ? m_resetEmptyFields->GetValue()
  125. : m_resetFieldText->GetValue();
  126. if( resetText )
  127. field.SetText( parentField->GetText() );
  128. if( resetVis )
  129. {
  130. field.SetVisible( parentField->IsVisible() );
  131. field.SetNameShown( parentField->IsNameShown() );
  132. }
  133. if( resetEffects )
  134. {
  135. // Careful: the visible bit and position are also set by SetAttributes()
  136. bool visible = field.IsVisible();
  137. VECTOR2I pos = field.GetPosition();
  138. field.SetAttributes( *parentField );
  139. field.SetVisible( visible );
  140. field.SetPosition( pos );
  141. }
  142. if( resetPositions )
  143. field.SetTextPos( parentField->GetTextPos() );
  144. }
  145. else if( removeExtras )
  146. {
  147. copy = false;
  148. }
  149. }
  150. if( copy )
  151. result.emplace_back( std::move( field ) );
  152. }
  153. std::vector<LIB_FIELD*> parentFields;
  154. int idx = result.size();
  155. flattenedParent->GetFields( parentFields );
  156. for( LIB_FIELD* parentField : parentFields )
  157. {
  158. if( !alg::contains( m_updateFields, parentField->GetName() ) )
  159. continue;
  160. if( !m_symbol->FindField( parentField->GetName() ) )
  161. {
  162. result.emplace_back( m_symbol, idx++ );
  163. LIB_FIELD* newField = &result.back();
  164. newField->SetName( parentField->GetCanonicalName() );
  165. newField->SetText( parentField->GetText() );
  166. newField->SetAttributes( *parentField ); // Includes visible bit and position
  167. }
  168. }
  169. m_symbol->SetFields( result );
  170. commit.Push( _( "Update Symbol Fields" ) );
  171. m_editFrame->RebuildView();
  172. wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
  173. }