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
6.9 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 The 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. DIALOG_UPDATE_SYMBOL_FIELDS::DIALOG_UPDATE_SYMBOL_FIELDS( SYMBOL_EDIT_FRAME* aParent, LIB_SYMBOL* aSymbol ) :
  28. DIALOG_UPDATE_SYMBOL_FIELDS_BASE( aParent ),
  29. m_editFrame( aParent ),
  30. m_symbol( aSymbol)
  31. {
  32. wxASSERT( aParent );
  33. wxASSERT( aSymbol );
  34. m_parentSymbolReadOnly->SetValue( UnescapeString( m_symbol->GetParent().lock()->GetName() ) );
  35. for( FIELD_T fieldId : MANDATORY_FIELDS )
  36. {
  37. m_mandatoryFieldListIndexes[fieldId] = m_fieldsBox->GetCount();
  38. m_fieldsBox->Append( GetDefaultFieldName( fieldId, DO_TRANSLATE ) );
  39. m_fieldsBox->Check( m_fieldsBox->GetCount() - 1, true );
  40. }
  41. updateFieldsList();
  42. SetupStandardButtons();
  43. // Now all widgets have the size fixed, call FinishDialogSettings
  44. finishDialogSettings();
  45. }
  46. void DIALOG_UPDATE_SYMBOL_FIELDS::updateFieldsList()
  47. {
  48. // Load non-mandatory fields from the parent part
  49. std::vector<SCH_FIELD*> libFields;
  50. std::set<wxString> fieldNames;
  51. std::unique_ptr<LIB_SYMBOL> flattenedParent = m_symbol->GetParent().lock()->Flatten();
  52. flattenedParent->GetFields( libFields );
  53. for( SCH_FIELD* libField : libFields )
  54. {
  55. if( !libField->IsMandatory() )
  56. fieldNames.insert( libField->GetName() );
  57. }
  58. libFields.clear(); // flattenedPart is about to go out of scope...
  59. // Load non-mandatory fields from the editor symbol
  60. m_symbol->GetFields( libFields );
  61. for( SCH_FIELD* libField : libFields )
  62. {
  63. if( !libField->IsMandatory() )
  64. fieldNames.insert( libField->GetName() );
  65. }
  66. auto isMandatoryField =
  67. [&]( int listbox_idx )
  68. {
  69. for( FIELD_T fieldId : MANDATORY_FIELDS )
  70. {
  71. if( m_mandatoryFieldListIndexes[fieldId] == listbox_idx )
  72. return true;
  73. }
  74. return false;
  75. };
  76. libFields.clear();
  77. // Update the listbox widget
  78. for( int i = (int) m_fieldsBox->GetCount() - 1; i >= 0; --i )
  79. {
  80. if( !isMandatoryField( i ) )
  81. m_fieldsBox->Delete( i );
  82. }
  83. for( const wxString& fieldName : fieldNames )
  84. m_fieldsBox->Append( fieldName );
  85. for( int i = 0; i < (int) m_fieldsBox->GetCount(); ++i )
  86. {
  87. if( !isMandatoryField( i ) )
  88. m_fieldsBox->Check( i, true );
  89. }
  90. }
  91. void DIALOG_UPDATE_SYMBOL_FIELDS::checkAll( bool aCheck )
  92. {
  93. for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
  94. m_fieldsBox->Check( i, aCheck );
  95. }
  96. void DIALOG_UPDATE_SYMBOL_FIELDS::onOkButtonClicked( wxCommandEvent& aEvent )
  97. {
  98. wxBusyCursor dummy;
  99. SCH_COMMIT commit( m_editFrame );
  100. commit.Modify( m_symbol, m_editFrame->GetScreen() );
  101. // Create the set of fields to be updated
  102. m_updateFields.clear();
  103. for( unsigned i = 0; i < m_fieldsBox->GetCount(); ++i )
  104. {
  105. if( m_fieldsBox->IsChecked( i ) )
  106. m_updateFields.insert( m_fieldsBox->GetString( i ) );
  107. }
  108. std::unique_ptr<LIB_SYMBOL> flattenedParent = m_symbol->GetParent().lock()->Flatten();
  109. bool removeExtras = m_removeExtraBox->GetValue();
  110. bool resetVis = m_resetFieldVisibilities->GetValue();
  111. bool resetEffects = m_resetFieldEffects->GetValue();
  112. bool resetPositions = m_resetFieldPositions->GetValue();
  113. std::vector<SCH_FIELD> fields;
  114. std::vector<SCH_FIELD> result;
  115. m_symbol->CopyFields( fields );
  116. for( SCH_FIELD& field : fields )
  117. {
  118. bool copy = true;
  119. SCH_FIELD* parentField = nullptr;
  120. if( alg::contains( m_updateFields, field.GetName() ) )
  121. {
  122. if( field.IsMandatory() )
  123. parentField = flattenedParent->GetField( field.GetId() );
  124. else
  125. parentField = flattenedParent->GetField( field.GetName() );
  126. if( parentField )
  127. {
  128. bool resetText = parentField->GetText().IsEmpty() ? m_resetEmptyFields->GetValue()
  129. : m_resetFieldText->GetValue();
  130. if( resetText )
  131. field.SetText( parentField->GetText() );
  132. if( resetVis )
  133. {
  134. field.SetVisible( parentField->IsVisible() );
  135. field.SetNameShown( parentField->IsNameShown() );
  136. }
  137. if( resetEffects )
  138. {
  139. // Careful: the visible bit and position are also set by SetAttributes()
  140. bool visible = field.IsVisible();
  141. VECTOR2I pos = field.GetPosition();
  142. field.SetAttributes( *parentField );
  143. field.SetVisible( visible );
  144. field.SetPosition( pos );
  145. }
  146. if( resetPositions )
  147. field.SetTextPos( parentField->GetTextPos() );
  148. }
  149. else if( removeExtras )
  150. {
  151. copy = false;
  152. }
  153. }
  154. if( copy )
  155. result.emplace_back( std::move( field ) );
  156. }
  157. std::vector<SCH_FIELD*> parentFields;
  158. flattenedParent->GetFields( parentFields );
  159. for( SCH_FIELD* parentField : parentFields )
  160. {
  161. if( !alg::contains( m_updateFields, parentField->GetName() ) )
  162. continue;
  163. if( !m_symbol->GetField( parentField->GetName() ) )
  164. {
  165. result.emplace_back( m_symbol, FIELD_T::USER );
  166. SCH_FIELD* newField = &result.back();
  167. newField->SetName( parentField->GetCanonicalName() );
  168. newField->SetText( parentField->GetText() );
  169. newField->SetAttributes( *parentField ); // Includes visible bit and position
  170. }
  171. }
  172. m_symbol->SetFields( result );
  173. commit.Push( _( "Update Symbol Fields" ) );
  174. m_editFrame->RebuildView();
  175. wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
  176. }