Eeschema: Adding back annotation

ADDED: Back annotation algorithm,
eeschema back annotation dialog

CHANGED: added some minor helper methods to SCH_REFERENCE_LIST and SCH_REFERENCE,
split SCH_REFERENCE_LIST::CheckAnnotation on 2 parts to reuse code
This commit is contained in:
Alexander Shuklin 2020-01-29 16:33:57 +00:00 committed by Seth Hillbrand
parent 970a0a593a
commit 3d0b3a51f3
23 changed files with 1647 additions and 124 deletions

View File

@ -527,6 +527,10 @@ TOOL_ACTION ACTIONS::updatePcbFromSchematic( "common.Control.updatePcbFromSchema
_( "Update PCB from Schematic..." ), _( "Push changes from schematic to PCB" ),
update_pcb_from_sch_xpm );
TOOL_ACTION ACTIONS::updateSchematicFromPcb( "common.Control.updateSchematicFromPCB", AS_GLOBAL, 0,
LEGACY_HK_NAME( "Update Schematic from PCB" ), _( "Update Schematic from PCB..." ),
_( "Push changes from PCB to Schematic" ), update_pcb_from_sch_xpm );
TOOL_ACTION ACTIONS::acceleratedGraphics( "common.Control.acceleratedGraphics",
AS_GLOBAL,
#ifdef __WXMAC__

View File

@ -92,6 +92,8 @@ set( EESCHEMA_DLGS
dialogs/dialog_symbol_remap_base.cpp
dialogs/dialog_update_fields.cpp
dialogs/dialog_update_fields_base.cpp
dialogs/dialog_update_from_pcb.cpp
dialogs/dialog_update_from_pcb_base.cpp
dialogs/panel_eeschema_template_fieldnames.cpp
dialogs/panel_eeschema_template_fieldnames_base.cpp
dialogs/panel_eeschema_display_options.cpp
@ -218,6 +220,7 @@ set( EESCHEMA_SRCS
netlist_exporters/netlist_exporter_orcadpcb2.cpp
netlist_exporters/netlist_exporter_pspice.cpp
tools/backannotate.cpp
tools/backanno.cpp
tools/ee_actions.cpp
tools/ee_inspection_tool.cpp

View File

@ -162,6 +162,13 @@ int SCH_REFERENCE_LIST::FindUnit( size_t aIndex, int aUnit )
return -1;
}
int SCH_REFERENCE_LIST::FindRefByPath( const wxString& aPath ) const
{
for( size_t i = 0; i < componentFlatList.size(); ++i )
if( componentFlatList[i].GetPath() == aPath )
return i;
return -1;
}
void SCH_REFERENCE_LIST::RemoveSubComponentsFromList()
{
@ -531,6 +538,32 @@ void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId, int
}
}
int SCH_REFERENCE_LIST::checkForDuplicatedElements( REPORTER& aReporter )
{
int error = 0;
wxString msg;
for( size_t ii = 0; ii < componentFlatList.size() - 1; ii++ )
{
if( ( componentFlatList[ii].m_TimeStamp != componentFlatList[ii + 1].m_TimeStamp )
|| ( componentFlatList[ii].GetSheetPath()
!= componentFlatList[ii + 1].GetSheetPath() ) )
continue;
// Same time stamp found.
wxString full_path;
full_path.Printf( wxT( "%s%8.8X" ), GetChars( componentFlatList[ii].GetSheetPath().Path() ),
componentFlatList[ii].m_TimeStamp );
msg.Printf( _( "Duplicate time stamp (%s) for %s%d and %s%d" ), full_path,
componentFlatList[ii].GetRef(), componentFlatList[ii].m_NumRef,
componentFlatList[ii + 1].GetRef(), componentFlatList[ii + 1].m_NumRef );
aReporter.Report( msg, REPORTER::RPT_WARNING );
error++;
}
return error;
}
int SCH_REFERENCE_LIST::CheckAnnotation( REPORTER& aReporter )
{
@ -694,30 +727,7 @@ int SCH_REFERENCE_LIST::CheckAnnotation( REPORTER& aReporter )
// count the duplicated time stamps
SortByTimeStamp();
for( int ii = 0; ii < imax; ii++ )
{
if( ( componentFlatList[ii].m_TimeStamp != componentFlatList[ii + 1].m_TimeStamp )
|| ( componentFlatList[ii].GetSheetPath() != componentFlatList[ii + 1].GetSheetPath() ) )
continue;
// Same time stamp found.
wxString full_path;
full_path.Printf( wxT( "%s%8.8X" ),
GetChars( componentFlatList[ii].GetSheetPath().Path() ),
componentFlatList[ii].m_TimeStamp );
msg.Printf( _( "Duplicate time stamp (%s) for %s%d and %s%d" ),
full_path,
componentFlatList[ii].GetRef(),
componentFlatList[ii].m_NumRef,
componentFlatList[ii + 1].GetRef(),
componentFlatList[ii + 1].m_NumRef );
aReporter.Report( msg, REPORTER::RPT_WARNING );
error++;
}
error += checkForDuplicatedElements( aReporter );
return error;
}

View File

@ -453,6 +453,10 @@ void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
payload = "success";
break;
case MAIL_SCH_UPDATE:
m_toolManager->RunAction( ACTIONS::updateSchematicFromPcb, true );
break;
default:
;
}

View File

@ -0,0 +1,133 @@
/**
* @file eeschema/dialogs/dialog_update_from_pcb.cpp
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com>
* Copyright (C) 1992-2019 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 2
* 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, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <backannotate.h>
#include <class_draw_panel_gal.h>
#include <common.h>
#include <confirm.h>
#include <dialog_update_from_pcb.h>
#include <functional>
#include <sch_edit_frame.h>
#include <sch_editor_control.h>
#include <tool/tool_manager.h>
#include <view/view.h>
#include <wx_html_report_panel.h>
// Saved dialog settings
DIALOG_UPDATE_FROM_PCB::DIALOG_UPDATE_FROM_PCB_SAVED_STATE
DIALOG_UPDATE_FROM_PCB::s_savedDialogState{ true, false, false, false };
DIALOG_UPDATE_FROM_PCB::DIALOG_UPDATE_FROM_PCB( SCH_EDIT_FRAME* aParent )
: DIALOG_UPDATE_FROM_PCB_BASE( aParent ),
m_frame( aParent ),
m_editorControl( m_frame->GetToolManager()->GetTool<SCH_EDITOR_CONTROL>() )
{
m_messagePanel->SetLabel( _( "Changes To Be Applied" ) );
m_messagePanel->SetLazyUpdate( true );
m_messagePanel->GetSizer()->SetSizeHints( this );
m_cbUpdateReferences->SetValue( s_savedDialogState.UpdateReferences );
m_cbUpdateFootprints->SetValue( s_savedDialogState.UpdateFootprints );
m_cbUpdateValues->SetValue( s_savedDialogState.UpdateValues );
m_cbIgnoreOtherProjects->SetValue( s_savedDialogState.IgnoreOtherProjectsErrors );
// We use a sdbSizer to get platform-dependent ordering of the action buttons, but
// that requires us to correct the button labels here.
m_sdbSizer1OK->SetLabel( _( "Update Schematic" ) );
m_sdbSizer1Cancel->SetLabel( _( "Close" ) );
m_sdbSizer1->Layout();
m_sdbSizer1OK->SetDefault();
FinishDialogSettings();
}
BACK_ANNOTATE::SETTINGS DIALOG_UPDATE_FROM_PCB::getSettings( bool aDryRun )
{
return BACK_ANNOTATE::SETTINGS{ m_messagePanel->Reporter(), m_cbUpdateFootprints->GetValue(),
m_cbUpdateValues->GetValue(), m_cbUpdateReferences->GetValue(),
m_cbIgnoreOtherProjects->GetValue(), aDryRun };
}
void DIALOG_UPDATE_FROM_PCB::updateData()
{
bool successfulRun = false;
m_messagePanel->Clear();
BACK_ANNOTATE backAnno( this->m_frame, getSettings( true ) );
std::string netlist;
if( backAnno.FetchNetlistFromPCB( netlist ) )
successfulRun = backAnno.BackAnnotateSymbols( netlist );
m_sdbSizer1OK->Enable( successfulRun );
m_messagePanel->Flush( false );
}
bool DIALOG_UPDATE_FROM_PCB::TransferDataToWindow()
{
updateData();
return true;
}
DIALOG_UPDATE_FROM_PCB::~DIALOG_UPDATE_FROM_PCB()
{
}
void DIALOG_UPDATE_FROM_PCB::OnOptionChanged( wxCommandEvent& event )
{
updateData();
s_savedDialogState.UpdateReferences = m_cbUpdateReferences->GetValue();
s_savedDialogState.UpdateFootprints = m_cbUpdateFootprints->GetValue();
s_savedDialogState.UpdateValues = m_cbUpdateValues->GetValue();
s_savedDialogState.IgnoreOtherProjectsErrors = m_cbIgnoreOtherProjects->GetValue();
}
void DIALOG_UPDATE_FROM_PCB::OnUpdateClick( wxCommandEvent& event )
{
KIDIALOG dlg( this,
_( "\n\nThis operation will change the existing annotation and cannot be undone." ),
_( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
dlg.SetOKLabel( _( "Back annotate" ) );
dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
if( dlg.ShowModal() == wxID_CANCEL )
return;
std::string netlist;
m_messagePanel->Clear();
BACK_ANNOTATE backAnno( this->m_frame, getSettings( false ) );
if( backAnno.FetchNetlistFromPCB( netlist ) && backAnno.BackAnnotateSymbols( netlist ) )
{
g_CurrentSheet->UpdateAllScreenReferences();
m_frame->SetSheetNumberAndCount();
m_frame->SyncView();
m_frame->OnModify();
m_frame->GetCanvas()->Refresh();
}
m_messagePanel->Flush( true );
}

View File

@ -0,0 +1,79 @@
/**
* @file eeschema/dialogs/dialog_update_from_pcb.h
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com>
* Copyright (C) 1992-2019 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 2
* 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, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _DIALOG_UPDATE_FROM_PCB_H_
#define _DIALOG_UPDATE_FROM_PCB_H_
#include <backannotate.h>
#include <dialog_update_from_pcb_base.h>
// Forward declarations
class SCH_EDIT_FRAME;
class SCH_EDITOR_CONTROL;
class DIALOG_UPDATE_FROM_PCB : public DIALOG_UPDATE_FROM_PCB_BASE
{
/**
* Struct containing the dialog last saved state
*/
struct DIALOG_UPDATE_FROM_PCB_SAVED_STATE
{
// Flags to remember last checkboxes state
bool UpdateReferences;
bool UpdateFootprints;
bool UpdateValues;
bool IgnoreOtherProjectsErrors;
};
static DIALOG_UPDATE_FROM_PCB_SAVED_STATE s_savedDialogState;
private:
SCH_EDIT_FRAME* m_frame;
SCH_EDITOR_CONTROL* m_editorControl;
public:
DIALOG_UPDATE_FROM_PCB( SCH_EDIT_FRAME* aParent );
~DIALOG_UPDATE_FROM_PCB();
private:
void updateData();
/**
* @brief Creates back annotate settings from dialog ui
* @param aDryRun - is it dry run
* @return back annotation settings structure
*/
BACK_ANNOTATE::SETTINGS getSettings( bool aDryRun );
bool TransferDataToWindow() override;
void OnOptionChanged( wxCommandEvent& event ) override;
void OnUpdateClick( wxCommandEvent& event ) override;
};
#endif

View File

@ -0,0 +1,110 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Sep 1 2019)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "wx_html_report_panel.h"
#include "dialog_update_from_pcb_base.h"
///////////////////////////////////////////////////////////////////////////
DIALOG_UPDATE_FROM_PCB_BASE::DIALOG_UPDATE_FROM_PCB_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
wxBoxSizer* bMainSizer;
bMainSizer = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* bUpperSizer;
bUpperSizer = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* sbSizer1;
sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Options") ), wxVERTICAL );
wxBoxSizer* bSizer1;
bSizer1 = new wxBoxSizer( wxVERTICAL );
sbSizer1->Add( bSizer1, 1, wxEXPAND, 5 );
wxGridBagSizer* gbSizer2;
gbSizer2 = new wxGridBagSizer( 0, 0 );
gbSizer2->SetFlexibleDirection( wxBOTH );
gbSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_ALL );
m_cbUpdateReferences = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Update references"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbUpdateReferences->SetValue(true);
m_cbUpdateReferences->SetToolTip( _("Update references of symbols that have been changed in the PCB editor.") );
gbSizer2->Add( m_cbUpdateReferences, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALL, 5 );
m_cbUpdateFootprints = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Update footprints"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbUpdateFootprints->SetToolTip( _("Update footprint associations of symbols whose footprints have been replaced with different footprints in PCB.") );
gbSizer2->Add( m_cbUpdateFootprints, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALL, 5 );
m_cbUpdateValues = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Update values"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbUpdateValues->SetToolTip( _("Update symbols values that have been replaced in the PCB editor.") );
gbSizer2->Add( m_cbUpdateValues, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxALL, 5 );
m_cbIgnoreOtherProjects = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Ignore errors in other projects"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbIgnoreOtherProjects->SetToolTip( _("Schematic sheets used in multiple projects are not compatible with back annotation. If this option is selected, errors generated by multiple use will be disabled.") );
gbSizer2->Add( m_cbIgnoreOtherProjects, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALL, 5 );
sbSizer1->Add( gbSizer2, 1, wxEXPAND, 5 );
bUpperSizer->Add( sbSizer1, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
bMainSizer->Add( bUpperSizer, 0, wxALL|wxEXPAND, 5 );
wxBoxSizer* bLowerSizer;
bLowerSizer = new wxBoxSizer( wxVERTICAL );
bLowerSizer->SetMinSize( wxSize( 660,300 ) );
m_messagePanel = new WX_HTML_REPORT_PANEL( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
bLowerSizer->Add( m_messagePanel, 1, wxEXPAND | wxALL, 5 );
bMainSizer->Add( bLowerSizer, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
m_sdbSizer1 = new wxStdDialogButtonSizer();
m_sdbSizer1OK = new wxButton( this, wxID_OK );
m_sdbSizer1->AddButton( m_sdbSizer1OK );
m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL );
m_sdbSizer1->AddButton( m_sdbSizer1Cancel );
m_sdbSizer1->Realize();
bMainSizer->Add( m_sdbSizer1, 0, wxALL|wxEXPAND, 5 );
this->SetSizer( bMainSizer );
this->Layout();
bMainSizer->Fit( this );
// Connect Events
m_cbUpdateReferences->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateFootprints->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateValues->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbIgnoreOtherProjects->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnUpdateClick ), NULL, this );
}
DIALOG_UPDATE_FROM_PCB_BASE::~DIALOG_UPDATE_FROM_PCB_BASE()
{
// Disconnect Events
m_cbUpdateReferences->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateFootprints->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbUpdateValues->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbIgnoreOtherProjects->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnOptionChanged ), NULL, this );
m_sdbSizer1OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_FROM_PCB_BASE::OnUpdateClick ), NULL, this );
}

View File

@ -0,0 +1,476 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="15" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file">dialog_update_from_pcb_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">dialog_update_from_pcb_base</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header"></property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_enum">1</property>
<property name="use_microsoft_bom">0</property>
<object class="Dialog" expanded="1">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="center"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="extra_style"></property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size">-1,-1</property>
<property name="name">DIALOG_UPDATE_FROM_PCB_BASE</property>
<property name="pos"></property>
<property name="size">-1,-1</property>
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
<property name="title">Update Schematic from PCB</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bMainSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bUpperSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
<property name="proportion">1</property>
<object class="wxStaticBoxSizer" expanded="1">
<property name="id">wxID_ANY</property>
<property name="label">Options</property>
<property name="minimum_size"></property>
<property name="name">sbSizer1</property>
<property name="orient">wxVERTICAL</property>
<property name="parent">1</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizer1</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxGridBagSizer" expanded="1">
<property name="empty_cell_size"></property>
<property name="flexible_direction">wxBOTH</property>
<property name="growablecols"></property>
<property name="growablerows"></property>
<property name="hgap">0</property>
<property name="minimum_size"></property>
<property name="name">gbSizer2</property>
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_ALL</property>
<property name="permission">none</property>
<property name="vgap">0</property>
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxALL</property>
<property name="row">0</property>
<property name="rowspan">1</property>
<object class="wxCheckBox" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">1</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Update references</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_cbUpdateReferences</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Update references of symbols that have been changed in the PCB editor.</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnCheckBox">OnOptionChanged</event>
</object>
</object>
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxALL</property>
<property name="row">1</property>
<property name="rowspan">1</property>
<object class="wxCheckBox" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Update footprints</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_cbUpdateFootprints</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Update footprint associations of symbols whose footprints have been replaced with different footprints in PCB.</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnCheckBox">OnOptionChanged</event>
</object>
</object>
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxALL</property>
<property name="row">2</property>
<property name="rowspan">1</property>
<object class="wxCheckBox" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Update values</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_cbUpdateValues</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Update symbols values that have been replaced in the PCB editor.</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnCheckBox">OnOptionChanged</event>
</object>
</object>
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">1</property>
<property name="flag">wxALL</property>
<property name="row">0</property>
<property name="rowspan">1</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Ignore errors in other projects</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_cbIgnoreOtherProjects</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Schematic sheets used in multiple projects are not compatible with back annotation. If this option is selected, errors generated by multiple use will be disabled.</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnCheckBox">OnOptionChanged</event>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="0">
<property name="minimum_size">660,300</property>
<property name="name">bLowerSizer</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxEXPAND | wxALL</property>
<property name="proportion">1</property>
<object class="wxPanel" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">-1,-1</property>
<property name="moveable">1</property>
<property name="name">m_messagePanel</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="subclass">WX_HTML_REPORT_PANEL; wx_html_report_panel.h</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxStdDialogButtonSizer" expanded="0">
<property name="Apply">0</property>
<property name="Cancel">1</property>
<property name="ContextHelp">0</property>
<property name="Help">0</property>
<property name="No">0</property>
<property name="OK">1</property>
<property name="Save">0</property>
<property name="Yes">0</property>
<property name="minimum_size"></property>
<property name="name">m_sdbSizer1</property>
<property name="permission">protected</property>
<event name="OnOKButtonClick">OnUpdateClick</event>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>

View File

@ -0,0 +1,60 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Sep 1 2019)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#pragma once
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
class WX_HTML_REPORT_PANEL;
#include "dialog_shim.h"
#include <wx/sizer.h>
#include <wx/gdicmn.h>
#include <wx/string.h>
#include <wx/checkbox.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/gbsizer.h>
#include <wx/statbox.h>
#include <wx/panel.h>
#include <wx/button.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_UPDATE_FROM_PCB_BASE
///////////////////////////////////////////////////////////////////////////////
class DIALOG_UPDATE_FROM_PCB_BASE : public DIALOG_SHIM
{
private:
protected:
wxCheckBox* m_cbUpdateReferences;
wxCheckBox* m_cbUpdateFootprints;
wxCheckBox* m_cbUpdateValues;
wxCheckBox* m_cbIgnoreOtherProjects;
WX_HTML_REPORT_PANEL* m_messagePanel;
wxStdDialogButtonSizer* m_sdbSizer1;
wxButton* m_sdbSizer1OK;
wxButton* m_sdbSizer1Cancel;
// Virtual event handlers, overide them in your derived class
virtual void OnOptionChanged( wxCommandEvent& event ) { event.Skip(); }
virtual void OnUpdateClick( wxCommandEvent& event ) { event.Skip(); }
public:
DIALOG_UPDATE_FROM_PCB_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Update Schematic from PCB"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_UPDATE_FROM_PCB_BASE();
};

View File

@ -260,6 +260,7 @@ void SCH_EDIT_FRAME::ReCreateMenuBar()
};
toolsMenu->AddItem( ACTIONS::updatePcbFromSchematic, EE_CONDITIONS::ShowAlways );
toolsMenu->AddItem( ACTIONS::updateSchematicFromPcb, EE_CONDITIONS::ShowAlways );
toolsMenu->AddItem( EE_ACTIONS::showPcbNew, EE_CONDITIONS::ShowAlways );
toolsMenu->AddSeparator();

View File

@ -93,21 +93,23 @@ public:
SCH_REFERENCE( SCH_COMPONENT* aComponent, LIB_PART* aLibComponent,
SCH_SHEET_PATH& aSheetPath );
SCH_COMPONENT* GetComp() const { return m_RootCmp; }
SCH_COMPONENT* GetComp() const { return m_RootCmp; }
LIB_PART* GetLibPart() const { return m_Entry; }
LIB_PART* GetLibPart() const { return m_Entry; }
const SCH_SHEET_PATH& GetSheetPath() const { return m_SheetPath; }
SCH_SHEET_PATH& GetSheetPath()
SCH_SHEET_PATH& GetSheetPath() { return m_SheetPath; }
int GetUnit() const { return m_Unit; }
void SetSheetNumber( int aSheetNumber ) { m_SheetNum = aSheetNumber; }
const wxString GetPath() const
{
return m_SheetPath;
return m_RootCmp ? m_RootCmp->GetPath( &m_SheetPath ) : "";
}
int GetUnit() const { return m_Unit; }
void SetSheetNumber( int aSheetNumber ) { m_SheetNum = aSheetNumber; }
/**
* Function Annotate
* updates the annotation of the component according the the current object state.
@ -145,6 +147,15 @@ public:
return m_Ref.c_str();
}
///> Return reference name with unit altogether
wxString GetFullRef()
{
if( GetComp()->GetUnitCount() > 1 )
return GetRef() + LIB_PART::SubReference( GetUnit() );
else
return GetRef();
}
wxString GetRefNumber() const
{
wxString ref;
@ -339,6 +350,14 @@ public:
*/
int CheckAnnotation( REPORTER& aReporter );
/**
* @brief Check components having same references designator. Must be called with references
* sorted by timestamp \ref SortByTimeStamp()
* @param aReporter A sink for error messages. Use NULL_REPORTER if you don't need errors.
* @return The number of errors found.
*/
int checkForDuplicatedElements( REPORTER& aReporter );
/**
* Function sortByXCoordinate
* sorts the list of references by X position.
@ -379,7 +398,7 @@ public:
/**
* Function SortComponentsByTimeStamp
* sort the flat list by Time Stamp.
* sort the flat list by Time Stamp (sheet path + timestamp).
* Useful to detect duplicate Time Stamps
*/
void SortByTimeStamp()
@ -433,6 +452,13 @@ public:
*/
int FindUnit( size_t aIndex, int aUnit );
/**
* @brief Searches unit with designated path
* @param aPath path to search
* @return index in aComponentsList if found or -1 if not found
*/
int FindRefByPath( const wxString& aPath ) const;
/**
* Function GetRefsInUse
* adds all the reference designator numbers greater than \a aMinRefId to \a aIdList
@ -481,6 +507,7 @@ public:
*/
static wxString Shorthand( std::vector<SCH_REFERENCE> aList );
friend class BACK_ANNOTATION;
private:
/* sort functions used to sort componentFlatList
@ -508,6 +535,9 @@ private:
* @return The first free (not yet used) value.
*/
int CreateFirstFreeRefId( std::vector<int>& aIdList, int aFirstValue );
// Used for sorting static sortByTimeStamp function
friend class BACK_ANNOTATE;
};
#endif // _SCH_REFERENCE_LIST_H_

View File

@ -0,0 +1,391 @@
/**
* @file eeschema/tools/backannotate.cpp
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com>
* Copyright (C) 2004-2019 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 2
* 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, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <backannotate.h>
#include <boost/property_tree/ptree.hpp>
#include <confirm.h>
#include <dsnlexer.h>
#include <kiface_i.h>
#include <macros.h>
#include <ptree.h>
#include <reporter.h>
#include <sch_edit_frame.h>
#include <sch_sheet_path.h>
#include <utf8.h>
BACK_ANNOTATE::BACK_ANNOTATE( SCH_EDIT_FRAME* aFrame, SETTINGS aSettings )
: m_settings( aSettings ),
m_frame( aFrame )
{
}
BACK_ANNOTATE::~BACK_ANNOTATE()
{
}
bool BACK_ANNOTATE::BackAnnotateSymbols( const std::string& aNetlist )
{
m_changesCount = 0;
wxString msg;
if( !m_settings.processValues && !m_settings.processFootprints
&& !m_settings.processReferences )
{
m_settings.reporter.ReportTail(
_( "Select at least one property to back annotate" ), REPORTER::RPT_ERROR );
return false;
}
int errors = getPcbModulesFromString( aNetlist );
SCH_SHEET_LIST sheets( g_RootSheet );
sheets.GetComponents( m_refs, false );
sheets.GetMultiUnitComponents( m_multiUnitsRefs );
m_refs.SortByTimeStamp();
errors += m_refs.checkForDuplicatedElements( m_settings.reporter );
errors += getChangeList();
errors += checkForUnusedSymbols();
errors += checkSharedSchematicErrors();
if( errors > 0 )
m_settings.dryRun = true;
applyChangelist();
if( !errors )
{
if( !m_settings.dryRun )
{
msg.Printf( _( "Schematic is back-annotated. %d changes applied." ), m_changesCount );
m_settings.reporter.ReportTail( msg, REPORTER::RPT_ACTION );
}
else
m_settings.reporter.ReportTail(
_( "No errors during dry run. Ready to go." ), REPORTER::RPT_ACTION );
}
else
{
msg.Printf( _( "Found %d errors. Fix them and run back annotation." ), errors );
m_settings.reporter.ReportTail( msg, REPORTER::RPT_ERROR );
}
return !errors;
}
bool BACK_ANNOTATE::FetchNetlistFromPCB( std::string& aNetlist )
{
if( Kiface().IsSingle() )
{
DisplayErrorMessage(
m_frame, _( "Cannot fetch PCB netlist because eeschema is opened in "
"stand-alone mode, you must launch the KiCad project manager "
"and create a project." ) );
return false;
}
KIWAY_PLAYER* player = m_frame->Kiway().Player( FRAME_PCB_EDITOR, false );
if( !player )
{
DisplayErrorMessage(
this->m_frame, _( "Please open Pcbnew and run back annotation again" ) );
return false;
}
m_frame->Kiway().ExpressMail( FRAME_PCB_EDITOR, MAIL_PCB_GET_NETLIST, aNetlist );
return true;
}
int BACK_ANNOTATE::getPcbModulesFromString( const std::string& aPayload )
{
DSNLEXER lexer( aPayload, FROM_UTF8( __func__ ) );
PTREE doc;
Scan( &doc, &lexer );
CPTREE& tree = doc.get_child( "pcb_netlist" );
wxString msg;
int errors = 0;
m_pcbModules.clear();
for( auto& item : tree )
{
wxString path, value, footprint;
wxASSERT( item.first == "ref" );
wxString ref = UTF8( item.second.front().first );
try
{
path = UTF8( item.second.get_child( "timestamp" ).front().first );
if( path == "" )
{
msg.Printf( _( "Footprint %s has no symbol associated." ), ref );
m_settings.reporter.ReportHead( msg, REPORTER::RPT_WARNING );
continue;
}
footprint = UTF8( item.second.get_child( "fpid" ).front().first );
value = UTF8( item.second.get_child( "value" ).front().first );
}
catch( ... )
{
wxLogWarning( "Cannot parse PCB netlist for back-annotation" );
}
// Use lower_bound for not to iterate over map twice
auto nearestItem = m_pcbModules.lower_bound( path );
if( nearestItem != m_pcbModules.end() && nearestItem->first == path )
{
// Module with this path already exists - generate error
msg.Printf( _( "Pcb footprints %s and %s linked to same symbol" ),
nearestItem->second->ref, ref );
m_settings.reporter.ReportHead( msg, REPORTER::RPT_ERROR );
++errors;
}
else
{
// Add module to the map
PCB_MODULE_DATA data( ref, footprint, value );
m_pcbModules.insert( nearestItem, decltype( PCB_MODULES_MAP::value_type() )( path,
std::make_shared<PCB_MODULE_DATA>( data ) ) );
}
}
return errors;
}
int BACK_ANNOTATE::getChangeList()
{
int errors = 0;
for( auto& module : m_pcbModules )
{
auto& pcbPath = module.first;
auto& pcbData = module.second;
bool foundInMultiunit = false;
for( auto& item : m_multiUnitsRefs )
{
auto& refList = item.second;
if( refList.FindRefByPath( pcbPath ) >= 0 )
{
// If module linked to multi unit symbol, we add all symbol's units to
// the change list
foundInMultiunit = true;
for( size_t i = 0; i < refList.GetCount(); ++i )
{
m_changelist.push_back( CHANGELIST_ITEM( refList[i], pcbData ) );
}
break;
}
}
if( foundInMultiunit )
continue;
int refIndex = m_refs.FindRefByPath( pcbPath );
if( refIndex >= 0 )
m_changelist.push_back( CHANGELIST_ITEM( m_refs[refIndex], pcbData ) );
else
{
// Haven't found linked symbol in multiunits or common refs. Generate error
wxString msg;
msg.Printf( _( "Cannot find symbol for %s footprint" ), pcbData->ref );
++errors;
m_settings.reporter.ReportTail( msg, REPORTER::RPT_ERROR );
}
}
return errors;
}
int BACK_ANNOTATE::checkForUnusedSymbols()
{
int errors = 0;
std::sort(
m_changelist.begin(), m_changelist.end(), []( CHANGELIST_ITEM a, CHANGELIST_ITEM b ) {
return SCH_REFERENCE_LIST::sortByTimeStamp( a.first, b.first );
} );
size_t i = 0;
for( auto& item : m_changelist )
{
// Refs and changelist are both sorted by paths, so we just go over m_refs and
// generate errors before we will find m_refs member to which item linked
while( i < m_refs.GetCount() && m_refs[i].GetPath() != item.first.GetPath() )
{
++errors;
wxString msg;
msg.Printf( _( "Cannot find footprint for %s symbol" ), m_refs[i++].GetFullRef() );
m_settings.reporter.ReportTail( msg, REPORTER::RPT_ERROR );
}
++i;
}
return errors;
}
bool BACK_ANNOTATE::checkReuseViolation( PCB_MODULE_DATA& aFirst, PCB_MODULE_DATA& aSecond )
{
if( m_settings.processFootprints && aFirst.footprint != aSecond.footprint )
return false;
if( m_settings.processValues && aFirst.value != aSecond.value )
return false;
return true;
}
wxString BACK_ANNOTATE::getTextFromField( const SCH_REFERENCE& aRef, const NumFieldType aField )
{
return aRef.GetComp()->GetField( aField )->GetText();
}
int BACK_ANNOTATE::checkSharedSchematicErrors()
{
std::sort(
m_changelist.begin(), m_changelist.end(), []( CHANGELIST_ITEM a, CHANGELIST_ITEM b ) {
return a.first.GetComp() > b.first.GetComp();
} );
// We don't check that if no footprints or values updating
if( !m_settings.processFootprints && !m_settings.processValues )
return 0;
int errors = 0;
// We will count how many times every component used in our changelist
// Component in this case is SCH_COMPONENT which can be used by more than one symbol
int usageCount = 1;
for( auto it = m_changelist.begin(); it != m_changelist.end(); ++it )
{
int compUsage = it->first.GetComp()->GetPathsAndReferences().Count();
if( compUsage == 1 )
continue;
// If that's not the last reference in list and references share same component
if( ( it + 1 ) != m_changelist.end() && it->first.GetComp() == ( it + 1 )->first.GetComp() )
{
++usageCount;
if( !checkReuseViolation( *it->second, *( it + 1 )->second ) )
{
// Refs share same component but have different values or footprints
++errors;
wxString msg;
msg.Printf( _( "%s and %s use the same schematic symbol. "
"They cannot have different footprints or values." ),
( it + 1 )->second->ref, it->second->ref );
m_settings.reporter.ReportTail( msg, REPORTER::RPT_ERROR );
}
}
else
{
/* Next ref uses different component, so we count all components number for current
one. We compare that number to stored in the component itself. If that differs, it
means that this particular component is reused in some another project. */
if( !m_settings.ignoreOtherProjects && compUsage > usageCount )
{
PCB_MODULE_DATA tmp{ "", getTextFromField( it->first, FOOTPRINT ),
getTextFromField( it->first, VALUE ) };
if( !checkReuseViolation( tmp, *it->second ) )
{
wxString msg;
msg.Printf( _( "Unable to change %s footprint or value because associated"
"symbol is reused in the another project" ),
it->second->ref );
m_settings.reporter.ReportTail( msg, REPORTER::RPT_ERROR );
++errors;
}
}
usageCount = 1;
}
}
return errors;
}
void BACK_ANNOTATE::applyChangelist()
{
wxString msg;
int leftUnchanged = 0;
// Apply changes from change list
for( auto& item : m_changelist )
{
SCH_REFERENCE& ref = item.first;
PCB_MODULE_DATA& module = *item.second;
wxString oldFootprint = getTextFromField( ref, FOOTPRINT );
wxString oldValue = getTextFromField( ref, VALUE );
int changesCountBefore = m_changesCount;
if( m_settings.processReferences && ref.GetRef() != module.ref )
{
++m_changesCount;
msg.Printf( _( "Change %s reference to %s." ), ref.GetFullRef(), module.ref );
if( !m_settings.dryRun )
ref.GetComp()->SetRef( &ref.GetSheetPath(), module.ref );
m_settings.reporter.ReportHead( msg, REPORTER::RPT_ACTION );
}
if( m_settings.processFootprints && oldFootprint != module.footprint )
{
++m_changesCount;
msg.Printf( _( "Change %s footprint from \"%s\" to \"%s\"." ), ref.GetFullRef(),
getTextFromField( ref, FOOTPRINT ), module.footprint );
if( !m_settings.dryRun )
ref.GetComp()->GetField( FOOTPRINT )->SetText( module.footprint );
m_settings.reporter.ReportHead( msg, REPORTER::RPT_ACTION );
}
if( m_settings.processValues && oldValue != module.value )
{
++m_changesCount;
msg.Printf( _( "Change %s value from %s to %s." ), ref.GetFullRef(),
getTextFromField( ref, VALUE ), module.value );
if( !m_settings.dryRun )
item.first.GetComp()->GetField( VALUE )->SetText( module.value );
m_settings.reporter.ReportHead( msg, REPORTER::RPT_ACTION );
}
if( changesCountBefore == m_changesCount )
++leftUnchanged;
}
msg.Printf( _( "%d symbols left unchanged" ), leftUnchanged );
m_settings.reporter.ReportHead( msg, REPORTER::RPT_INFO );
}

View File

@ -0,0 +1,167 @@
/**
* @file eeschema/tools/backannotate.h
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 Alexander Shuklin <Jasuramme@gmail.com>
* Copyright (C) 2004-2019 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 2
* 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, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef BACKANNOTATE_H
#define BACKANNOTATE_H
#include <deque>
#include <map>
#include <memory>
#include <sch_reference_list.h>
#include <template_fieldnames.h>
#include <wx/string.h>
// Forward declarations
class REPORTER;
class SCH_SHEET_LIST;
class SCH_EDIT_FRAME;
/**
* @brief Back annotation algorithm class. It used to recieve, check and apply \ref NETLIST
* from PCBNEW. Class check for following collisions:
* - Schematic symbol exists, but linked PCBnew module missing
* - PCBnew module exists but no schematic symbol connected to
* - PCBnew module is standalone
* - Schematic sheet is reused one or more times and user trying to change footprint or value
* only for few of them.
* - Schematic symbols share same path
* - More than one PCBnew module linked to same path
*/
class BACK_ANNOTATE
{
public:
/**
* @brief settings struct to set up back annotation
*/
struct SETTINGS
{
REPORTER& reporter;
bool processFootprints;
bool processValues;
bool processReferences;
bool ignoreOtherProjects;
bool dryRun;
};
/**
* @brief Struct to hold PCBnew module data
*/
struct PCB_MODULE_DATA
{
PCB_MODULE_DATA(wxString aRef, wxString aFootprint, wxString aValue) :
ref(aRef),
footprint(aFootprint),
value(aValue){};
wxString ref;
wxString footprint;
wxString value;
};
///> Map to hold NETLIST modules data
using PCB_MODULES_MAP = std::map<wxString, std::shared_ptr<PCB_MODULE_DATA>>;
using CHANGELIST_ITEM = std::pair<SCH_REFERENCE, std::shared_ptr<PCB_MODULE_DATA>>;
///> To hold match between reference and PCBnew module
using CHANGELIST = std::deque<CHANGELIST_ITEM>;
BACK_ANNOTATE( SCH_EDIT_FRAME* aFrame, SETTINGS aSettings );
~BACK_ANNOTATE();
/**
* @brief Get netlist from the PCBnew.
* @param aNetlist reference to where netlist will be stored
* @return true if success
*/
bool FetchNetlistFromPCB( std::string& aNetlist );
/**
* @brief Run back annotation algorithm. If any errors, back annotation doesn't run.
* only report
* @param aNetlist netlist to run back annotation from
* @return true if success
*/
bool BackAnnotateSymbols( const std::string& aNetlist );
private:
SETTINGS m_settings;
PCB_MODULES_MAP m_pcbModules;
SCH_REFERENCE_LIST m_refs;
SCH_MULTI_UNIT_REFERENCE_MAP m_multiUnitsRefs;
CHANGELIST m_changelist;
SCH_EDIT_FRAME* m_frame;
///> To count number of changes applied to the schematic
int m_changesCount;
///> Get text from symbol's field ( such as Footprint or Value )
wxString getTextFromField( const SCH_REFERENCE& aRef, const NumFieldType aField );
/**
* @brief Check if modules has different data. Check only if corresponding \ref m_settings
* flag is rised
* @param aFirst first module to compare
* @param aSecond second module to compare
* @return true if no violation
*/
bool checkReuseViolation( PCB_MODULE_DATA& aFirst, PCB_MODULE_DATA& aSecond );
/**
* @brief Parse netlist sent over KiWay epress mail interface and fill \ref m_pcbModules
* @param aPayload - netlist from PCBnew
* @return number of errors during parsing
*/
int getPcbModulesFromString( const std::string& aPayload );
///> Create changelist
int getChangeList();
/**
* @brief Check if some symbols are not represented in PCB modules and vice versa.
* \ref m_refs must be sorted by path
* @return number of errors
*/
int checkForUnusedSymbols();
/**
* @brief Check for errors connected to reusing schematic in project or between projects
* @return number of errors
*/
int checkSharedSchematicErrors();
/**
* @brief Apply changelist to the schematic
*/
void applyChangelist();
};
#endif

View File

@ -52,7 +52,7 @@
#include <dialogs/dialog_paste_special.h>
#include <netlist_exporters/netlist_exporter_pspice.h>
#include <math/util.h> // for KiROUND
#include <dialog_update_from_pcb.h>
int SCH_EDITOR_CONTROL::New( const TOOL_EVENT& aEvent )
{
@ -1220,6 +1220,14 @@ int SCH_EDITOR_CONTROL::UpdatePCB( const TOOL_EVENT& aEvent )
}
int SCH_EDITOR_CONTROL::UpdateFromPCB( const TOOL_EVENT& aEvent )
{
DIALOG_UPDATE_FROM_PCB dlg( m_frame );
dlg.ShowModal();
return 0;
}
int SCH_EDITOR_CONTROL::ExportNetlist( const TOOL_EVENT& aEvent )
{
int result = NET_PLUGIN_CHANGE;
@ -1364,6 +1372,7 @@ void SCH_EDITOR_CONTROL::setTransitions()
Go( &SCH_EDITOR_CONTROL::EditSymbolLibraryLinks,EE_ACTIONS::editSymbolLibraryLinks.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::ShowPcbNew, EE_ACTIONS::showPcbNew.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::UpdatePCB, ACTIONS::updatePcbFromSchematic.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::UpdateFromPCB, ACTIONS::updateSchematicFromPcb.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::ExportNetlist, EE_ACTIONS::exportNetlist.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::GenerateBOM, EE_ACTIONS::generateBOM.MakeEvent() );
Go( &SCH_EDITOR_CONTROL::DrawSheetOnClipboard, EE_ACTIONS::drawSheetOnClipboard.MakeEvent() );

View File

@ -105,6 +105,7 @@ public:
int EditSymbolLibraryLinks( const TOOL_EVENT& aEvent );
int ShowPcbNew( const TOOL_EVENT& aEvent );
int UpdatePCB( const TOOL_EVENT& aEvent );
int UpdateFromPCB( const TOOL_EVENT& aEvent );
int ImportFPAssignments( const TOOL_EVENT& aEvent );
int ExportNetlist( const TOOL_EVENT& aEvent );
int GenerateBOM( const TOOL_EVENT& aEvent );

View File

@ -36,14 +36,16 @@
*/
enum MAIL_T
{
MAIL_CROSS_PROBE, ///< PCB<->SCH, CVPCB->SCH cross-probing.
MAIL_BACKANNOTATE_FOOTPRINTS, ///< CVPCB->SCH footprint stuffing
MAIL_SCH_SAVE, ///< CVPCB->SCH save the schematic
MAIL_EESCHEMA_NETLIST, ///< SCH->CVPCB netlist immediately after launching CVPCB
MAIL_PCB_UPDATE, ///< SCH->PCB forward update
MAIL_IMPORT_FILE, ///< Import a different format file
MAIL_SCH_GET_NETLIST, ///< Fetch a netlist
MAIL_SCH_REFRESH, ///< The the schematic editor to refresh the display.
MAIL_CROSS_PROBE, ///< PCB<->SCH, CVPCB->SCH cross-probing.
MAIL_BACKANNOTATE_FOOTPRINTS, ///< CVPCB->SCH footprint stuffing
MAIL_SCH_SAVE, ///< CVPCB->SCH save the schematic
MAIL_EESCHEMA_NETLIST, ///< SCH->CVPCB netlist immediately after launching CVPCB
MAIL_PCB_UPDATE, ///< SCH->PCB forward update
MAIL_SCH_UPDATE, ///< PCB->SCH forward update
MAIL_IMPORT_FILE, ///< Import a different format file
MAIL_SCH_GET_NETLIST, ///< Fetch a netlist from schematics
MAIL_PCB_GET_NETLIST, ///< Fetch a netlist from PCB layout
MAIL_SCH_REFRESH, ///< The the schematic editor to refresh the display.
MAIL_LIB_EDIT,
MAIL_FP_EDIT

View File

@ -151,6 +151,7 @@ public:
static TOOL_ACTION showFootprintBrowser;
static TOOL_ACTION showFootprintEditor;
static TOOL_ACTION updatePcbFromSchematic;
static TOOL_ACTION updateSchematicFromPcb;
static TOOL_ACTION acceleratedGraphics;
static TOOL_ACTION standardGraphics;

View File

@ -330,10 +330,24 @@ void PCB_EDIT_FRAME::SendCrossProbeNetName( const wxString& aNetName )
void PCB_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
{
const std::string& payload = mail.GetPayload();
std::string& payload = mail.GetPayload();
switch( mail.Command() )
{
case MAIL_PCB_GET_NETLIST:
{
NETLIST netlist;
STRING_FORMATTER sf;
for( auto& module : this->GetBoard()->Modules() )
{
netlist.AddComponent( new COMPONENT( module->GetFPID(), module->GetReference(),
module->GetValue(), module->GetPath() ) );
}
netlist.Format(
"pcb_netlist", &sf, 0, CTL_OMIT_FILTERS | CTL_OMIT_NETS | CTL_OMIT_FILTERS );
payload = sf.GetString();
break;
}
case MAIL_CROSS_PROBE:
ExecuteRemoteCommand( payload.c_str() );
break;

View File

@ -13,101 +13,101 @@
DIALOG_UPDATE_PCB_BASE::DIALOG_UPDATE_PCB_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
wxBoxSizer* bMainSizer;
bMainSizer = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* bMainSizer;
bMainSizer = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* bUpperSizer;
bUpperSizer = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* bUpperSizer;
bUpperSizer = new wxBoxSizer( wxVERTICAL );
wxString m_matchByTimestampChoices[] = { _("Update footprint references to match any changed symbol references"), _("Update footprint associations by existing references") };
int m_matchByTimestampNChoices = sizeof( m_matchByTimestampChoices ) / sizeof( wxString );
m_matchByTimestamp = new wxRadioBox( this, wxID_ANY, _("Match Method"), wxDefaultPosition, wxDefaultSize, m_matchByTimestampNChoices, m_matchByTimestampChoices, 1, wxRA_SPECIFY_COLS );
m_matchByTimestamp->SetSelection( 0 );
m_matchByTimestamp->SetToolTip( _("The first option uses the existing links between symbols and their footprints to update the footprints based on changes made to their symbols. \n\nThe second option uses the symbol and footprint references to establish a new set of links between symbols and footprints, and then updates the footprints accordingly.") );
wxString m_matchByTimestampChoices[] = { _("Update footprint references to match any changed symbol references"), _("Update footprint associations by existing references") };
int m_matchByTimestampNChoices = sizeof( m_matchByTimestampChoices ) / sizeof( wxString );
m_matchByTimestamp = new wxRadioBox( this, wxID_ANY, _("Match Method"), wxDefaultPosition, wxDefaultSize, m_matchByTimestampNChoices, m_matchByTimestampChoices, 1, wxRA_SPECIFY_COLS );
m_matchByTimestamp->SetSelection( 0 );
m_matchByTimestamp->SetToolTip( _("The first option uses the existing links between symbols and their footprints to update the footprints based on changes made to their symbols. \n\nThe second option uses the symbol and footprint references to establish a new set of links between symbols and footprints, and then updates the footprints accordingly.") );
bUpperSizer->Add( m_matchByTimestamp, 0, wxALIGN_TOP|wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
bUpperSizer->Add( m_matchByTimestamp, 0, wxALIGN_TOP|wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
wxStaticBoxSizer* sbSizer1;
sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Options") ), wxVERTICAL );
wxStaticBoxSizer* sbSizer1;
sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Options") ), wxVERTICAL );
wxGridBagSizer* gbSizer1;
gbSizer1 = new wxGridBagSizer( 2, 0 );
gbSizer1->SetFlexibleDirection( wxBOTH );
gbSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
wxGridBagSizer* gbSizer1;
gbSizer1 = new wxGridBagSizer( 2, 0 );
gbSizer1->SetFlexibleDirection( wxBOTH );
gbSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_cbUpdateFootprints = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Replace footprints of symbols whose footprint assignments have changed"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbUpdateFootprints->SetToolTip( _("Normally footprints on the board should be changed to match footprint assignment changes made in the schematic. Uncheck this only if you don't want to change existing footprints on the board.") );
m_cbUpdateFootprints = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Replace footprints of symbols whose footprint assignments have changed"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbUpdateFootprints->SetToolTip( _("Normally footprints on the board should be changed to match footprint assignment changes made in the schematic. Uncheck this only if you don't want to change existing footprints on the board.") );
gbSizer1->Add( m_cbUpdateFootprints, wxGBPosition( 0, 0 ), wxGBSpan( 1, 2 ), wxALL, 5 );
gbSizer1->Add( m_cbUpdateFootprints, wxGBPosition( 0, 0 ), wxGBSpan( 1, 2 ), wxALL, 5 );
m_cbDeleteExtraFootprints = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Delete footprints with no associated symbol"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbDeleteExtraFootprints->SetToolTip( _("Remove from the board not locked footprints, \nif they are not attached to a schematic symbol.") );
m_cbDeleteExtraFootprints = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Delete footprints with no associated symbol"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbDeleteExtraFootprints->SetToolTip( _("Remove from the board not locked footprints, \nif they are not attached to a schematic symbol.") );
gbSizer1->Add( m_cbDeleteExtraFootprints, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxBOTTOM|wxRIGHT|wxLEFT, 5 );
gbSizer1->Add( m_cbDeleteExtraFootprints, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_cbDeleteSinglePadNets = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Delete nets containing only a single pad"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbDeleteSinglePadNets->SetToolTip( _("Clear the net name of pads when there is only one pad belonging to this net.") );
m_cbDeleteSinglePadNets = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Delete nets containing only a single pad"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbDeleteSinglePadNets->SetToolTip( _("Clear the net name of pads when there is only one pad belonging to this net.") );
gbSizer1->Add( m_cbDeleteSinglePadNets, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxBOTTOM|wxRIGHT|wxLEFT, 5 );
gbSizer1->Add( m_cbDeleteSinglePadNets, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxBOTTOM|wxRIGHT|wxLEFT, 5 );
m_cbWarnNoNetPad = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Warn for no net pads"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbWarnNoNetPad->SetValue(true);
m_cbWarnNoNetPad->SetToolTip( _("Display a warning if a pad in a footprint does not appear in netlist.\nOnly pads on a copper layer and having a name are tested.") );
m_cbWarnNoNetPad = new wxCheckBox( sbSizer1->GetStaticBox(), wxID_ANY, _("Warn for no net pads"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbWarnNoNetPad->SetValue(true);
m_cbWarnNoNetPad->SetToolTip( _("Display a warning if a pad in a footprint does not appear in netlist.\nOnly pads on a copper layer and having a name are tested.") );
gbSizer1->Add( m_cbWarnNoNetPad, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxBOTTOM|wxRIGHT|wxLEFT, 5 );
gbSizer1->Add( m_cbWarnNoNetPad, wxGBPosition( 2, 0 ), wxGBSpan( 1, 1 ), wxBOTTOM|wxRIGHT|wxLEFT, 5 );
sbSizer1->Add( gbSizer1, 1, wxEXPAND, 5 );
sbSizer1->Add( gbSizer1, 1, wxEXPAND, 5 );
bUpperSizer->Add( sbSizer1, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
bUpperSizer->Add( sbSizer1, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
bMainSizer->Add( bUpperSizer, 0, wxALL|wxEXPAND, 5 );
bMainSizer->Add( bUpperSizer, 0, wxALL|wxEXPAND, 5 );
wxBoxSizer* bLowerSizer;
bLowerSizer = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* bLowerSizer;
bLowerSizer = new wxBoxSizer( wxVERTICAL );
bLowerSizer->SetMinSize( wxSize( 660,300 ) );
m_messagePanel = new WX_HTML_REPORT_PANEL( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
bLowerSizer->Add( m_messagePanel, 1, wxEXPAND | wxALL, 5 );
bLowerSizer->SetMinSize( wxSize( 660,300 ) );
m_messagePanel = new WX_HTML_REPORT_PANEL( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
bLowerSizer->Add( m_messagePanel, 1, wxEXPAND | wxALL, 5 );
bMainSizer->Add( bLowerSizer, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
bMainSizer->Add( bLowerSizer, 1, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
m_sdbSizer1 = new wxStdDialogButtonSizer();
m_sdbSizer1OK = new wxButton( this, wxID_OK );
m_sdbSizer1->AddButton( m_sdbSizer1OK );
m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL );
m_sdbSizer1->AddButton( m_sdbSizer1Cancel );
m_sdbSizer1->Realize();
m_sdbSizer1 = new wxStdDialogButtonSizer();
m_sdbSizer1OK = new wxButton( this, wxID_OK );
m_sdbSizer1->AddButton( m_sdbSizer1OK );
m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL );
m_sdbSizer1->AddButton( m_sdbSizer1Cancel );
m_sdbSizer1->Realize();
bMainSizer->Add( m_sdbSizer1, 0, wxALL|wxEXPAND, 5 );
bMainSizer->Add( m_sdbSizer1, 0, wxALL|wxEXPAND, 5 );
this->SetSizer( bMainSizer );
this->Layout();
bMainSizer->Fit( this );
this->SetSizer( bMainSizer );
this->Layout();
bMainSizer->Fit( this );
// Connect Events
m_matchByTimestamp->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnMatchChanged ), NULL, this );
m_cbUpdateFootprints->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbDeleteExtraFootprints->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbDeleteSinglePadNets->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbWarnNoNetPad->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnUpdateClick ), NULL, this );
// Connect Events
m_matchByTimestamp->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnMatchChanged ), NULL, this );
m_cbUpdateFootprints->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbDeleteExtraFootprints->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbDeleteSinglePadNets->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbWarnNoNetPad->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnUpdateClick ), NULL, this );
}
DIALOG_UPDATE_PCB_BASE::~DIALOG_UPDATE_PCB_BASE()
{
// Disconnect Events
m_matchByTimestamp->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnMatchChanged ), NULL, this );
m_cbUpdateFootprints->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbDeleteExtraFootprints->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbDeleteSinglePadNets->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbWarnNoNetPad->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_sdbSizer1OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnUpdateClick ), NULL, this );
// Disconnect Events
m_matchByTimestamp->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnMatchChanged ), NULL, this );
m_cbUpdateFootprints->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbDeleteExtraFootprints->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbDeleteSinglePadNets->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_cbWarnNoNetPad->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnOptionChanged ), NULL, this );
m_sdbSizer1OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_UPDATE_PCB_BASE::OnUpdateClick ), NULL, this );
}

View File

@ -34,29 +34,29 @@ class WX_HTML_REPORT_PANEL;
///////////////////////////////////////////////////////////////////////////////
class DIALOG_UPDATE_PCB_BASE : public DIALOG_SHIM
{
private:
private:
protected:
wxRadioBox* m_matchByTimestamp;
wxCheckBox* m_cbUpdateFootprints;
wxCheckBox* m_cbDeleteExtraFootprints;
wxCheckBox* m_cbDeleteSinglePadNets;
wxCheckBox* m_cbWarnNoNetPad;
WX_HTML_REPORT_PANEL* m_messagePanel;
wxStdDialogButtonSizer* m_sdbSizer1;
wxButton* m_sdbSizer1OK;
wxButton* m_sdbSizer1Cancel;
protected:
wxRadioBox* m_matchByTimestamp;
wxCheckBox* m_cbUpdateFootprints;
wxCheckBox* m_cbDeleteExtraFootprints;
wxCheckBox* m_cbDeleteSinglePadNets;
wxCheckBox* m_cbWarnNoNetPad;
WX_HTML_REPORT_PANEL* m_messagePanel;
wxStdDialogButtonSizer* m_sdbSizer1;
wxButton* m_sdbSizer1OK;
wxButton* m_sdbSizer1Cancel;
// Virtual event handlers, overide them in your derived class
virtual void OnMatchChanged( wxCommandEvent& event ) { event.Skip(); }
virtual void OnOptionChanged( wxCommandEvent& event ) { event.Skip(); }
virtual void OnUpdateClick( wxCommandEvent& event ) { event.Skip(); }
// Virtual event handlers, overide them in your derived class
virtual void OnMatchChanged( wxCommandEvent& event ) { event.Skip(); }
virtual void OnOptionChanged( wxCommandEvent& event ) { event.Skip(); }
virtual void OnUpdateClick( wxCommandEvent& event ) { event.Skip(); }
public:
public:
DIALOG_UPDATE_PCB_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Update PCB from Schematic"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_UPDATE_PCB_BASE();
DIALOG_UPDATE_PCB_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Update PCB from Schematic"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_UPDATE_PCB_BASE();
};

View File

@ -471,6 +471,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
CONDITIONAL_MENU* toolsMenu = new CONDITIONAL_MENU( false, selTool );
toolsMenu->AddItem( ACTIONS::updatePcbFromSchematic, SELECTION_CONDITIONS::ShowAlways );
toolsMenu->AddItem( ACTIONS::updateSchematicFromPcb, SELECTION_CONDITIONS::ShowAlways );
toolsMenu->AddItem( PCB_ACTIONS::updateFootprints, SELECTION_CONDITIONS::ShowAlways );
#if defined(KICAD_SCRIPTING_WXPYTHON)

View File

@ -34,11 +34,14 @@
#include <class_pcb_target.h>
#include <class_zone.h>
#include <collectors.h>
#include <confirm.h>
#include <cstdint>
#include <dialogs/dialog_page_settings.h>
#include <dialogs/dialog_update_pcb.h>
#include <functional>
#include <gestfich.h>
#include <kiface_i.h>
#include <kiway.h>
#include <memory>
#include <netlist_reader/pcb_netlist.h>
#include <origin_viewitem.h>
@ -398,6 +401,28 @@ int PCB_EDITOR_CONTROL::UpdatePCBFromSchematic( const TOOL_EVENT& aEvent )
return 0;
}
int PCB_EDITOR_CONTROL::UpdateSchematicFromPCB( const TOOL_EVENT& aEvent )
{
if( Kiface().IsSingle() )
{
DisplayErrorMessage(
m_frame, _( "Cannot update schematic because Pcbnew is opened in stand-alone "
"mode. In order to create or update PCBs from schematics, you "
"must launch the KiCad project manager and create a project." ) );
return 0;
}
m_frame->RunEeschema();
KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_SCH, false );
if( frame )
{
std::string payload;
m_frame->Kiway().ExpressMail( FRAME_SCH, MAIL_SCH_UPDATE, payload, m_frame );
}
return 0;
}
int PCB_EDITOR_CONTROL::ShowEeschema( const TOOL_EVENT& aEvent )
{
@ -1166,6 +1191,7 @@ void PCB_EDITOR_CONTROL::setTransitions()
Go( &PCB_EDITOR_CONTROL::UnlockSelected, PCB_ACTIONS::unlock.MakeEvent() );
Go( &PCB_EDITOR_CONTROL::UpdatePCBFromSchematic, ACTIONS::updatePcbFromSchematic.MakeEvent() );
Go( &PCB_EDITOR_CONTROL::UpdateSchematicFromPCB, ACTIONS::updateSchematicFromPcb.MakeEvent() );
Go( &PCB_EDITOR_CONTROL::ShowEeschema, PCB_ACTIONS::showEeschema.MakeEvent() );
Go( &PCB_EDITOR_CONTROL::ToggleLayersManager, PCB_ACTIONS::showLayersManager.MakeEvent() );
Go( &PCB_EDITOR_CONTROL::ToggleMicrowaveToolbar, PCB_ACTIONS::showMicrowaveToolbar.MakeEvent() );

View File

@ -68,6 +68,7 @@ public:
int GenerateFabFiles( const TOOL_EVENT& aEvent );
int UpdatePCBFromSchematic( const TOOL_EVENT& aEvent );
int UpdateSchematicFromPCB( const TOOL_EVENT& aEvent );
int ShowEeschema( const TOOL_EVENT& aEvent );
int ToggleLayersManager( const TOOL_EVENT& aEvent );
int ToggleMicrowaveToolbar( const TOOL_EVENT& aEvent );