diff --git a/common/lset.cpp b/common/lset.cpp index 17cec5b411..2c17854799 100644 --- a/common/lset.cpp +++ b/common/lset.cpp @@ -134,6 +134,9 @@ const wxChar* LSET::Name( PCB_LAYER_ID aLayerId ) case F_Fab: txt = wxT( "F.Fab" ); break; case B_Fab: txt = wxT( "B.Fab" ); break; + // Rescue + case Rescue: txt = wxT( "Rescue" ); break; + default: std::cout << aLayerId << std::endl; wxASSERT_MSG( 0, wxT( "aLayerId out of range" ) ); diff --git a/include/layers_id_colors_and_visibility.h b/include/layers_id_colors_and_visibility.h index 00829a007e..d6e1f79ceb 100644 --- a/include/layers_id_colors_and_visibility.h +++ b/include/layers_id_colors_and_visibility.h @@ -134,6 +134,8 @@ enum PCB_LAYER_ID: int B_Fab, F_Fab, + Rescue, + PCB_LAYER_ID_COUNT }; diff --git a/kicad/mainframe.cpp b/kicad/mainframe.cpp index 72374428fd..709d52b479 100644 --- a/kicad/mainframe.cpp +++ b/kicad/mainframe.cpp @@ -308,7 +308,9 @@ void KICAD_MANAGER_FRAME::RunEeschema( const wxString& aProjectSchematicFileName if( !frame->IsShown() ) // A hidden frame might not have the project loaded. { - frame->OpenProjectFiles( std::vector( 1, aProjectSchematicFileName ) ); + if( !frame->OpenProjectFiles( std::vector( 1, aProjectSchematicFileName ) ) ) + return; + frame->Show( true ); } @@ -377,7 +379,9 @@ void KICAD_MANAGER_FRAME::RunPcbNew( const wxString& aProjectBoardFileName ) if( !frame->IsVisible() ) // A hidden frame might not have the board loaded. { - frame->OpenProjectFiles( std::vector( 1, aProjectBoardFileName ) ); + if( !frame->OpenProjectFiles( std::vector( 1, aProjectBoardFileName ) ) ) + return; + frame->Show( true ); } diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp index 0a86ee1905..b46af64ee4 100644 --- a/pcbnew/files.cpp +++ b/pcbnew/files.cpp @@ -505,9 +505,12 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector& aFileSet, in } catch( const IO_ERROR& ioe ) { - DisplayErrorMessage( this, - wxString::Format( _( "Error loading board file:\n%s" ), fullFileName ), - ioe.What() ); + if( ioe.Problem() != wxT( "CANCEL" ) ) + { + wxString msg = wxString::Format( _( "Error loading board file:\n%s" ), fullFileName ); + DisplayErrorMessage( this, msg, ioe.What() ); + } + return false; } diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index dce98b1adf..91de6234b4 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -580,6 +580,88 @@ BOARD* PCB_PARSER::parseBOARD_unchecked() } } + if( m_undefinedLayers.size() > 0 ) + { + bool deleteItems; + std::vector deleteList; + wxString msg = wxString::Format( _( "Items found on undefined layers. Do you wish to\n" + "rescue them to the Cmts.User layer?" ) ); + wxString details = wxString::Format( _( "Undefined layers:" ) ); + + for( const wxString& undefinedLayer : m_undefinedLayers ) + details += wxT( "\n " ) + undefinedLayer; + + wxRichMessageDialog dlg( nullptr, msg, _( "Warning" ), + wxYES_NO | wxCANCEL | wxCENTRE | wxICON_WARNING | wxSTAY_ON_TOP ); + dlg.ShowDetailedText( details ); + dlg.SetYesNoCancelLabels( _( "Rescue" ), _( "Delete" ), _( "Cancel" ) ); + + switch( dlg.ShowModal() ) + { + case wxID_YES: deleteItems = false; break; + case wxID_NO: deleteItems = true; break; + case wxID_CANCEL: + default: THROW_IO_ERROR( wxT( "CANCEL" ) ); + } + + auto visitItem = [&]( BOARD_ITEM* item ) + { + if( item->GetLayer() == Rescue ) + { + if( deleteItems ) + deleteList.push_back( item ); + else + item->SetLayer( Cmts_User ); + } + }; + + for( TRACK* segm = m_board->m_Track; segm; segm = segm->Next() ) + { + if( segm->Type() == PCB_VIA_T ) + { + VIA* via = (VIA*) segm; + PCB_LAYER_ID top_layer, bottom_layer; + + if( via->GetViaType() == VIA_THROUGH ) + continue; + + via->LayerPair( &top_layer, &bottom_layer ); + + if( top_layer == Rescue || bottom_layer == Rescue ) + { + if( deleteItems ) + deleteList.push_back( via ); + else + { + if( top_layer == Rescue ) + top_layer = F_Cu; + + if( bottom_layer == Rescue ) + bottom_layer = B_Cu; + + via->SetLayerPair( top_layer, bottom_layer ); + } + } + } + else + visitItem( segm ); + } + + for( TRACK* segm = m_board->m_SegZoneDeprecated; segm; segm = segm->Next() ) + visitItem( segm ); + + for( BOARD_ITEM* zone : m_board->Zones() ) + visitItem( zone ); + + for( BOARD_ITEM* drawing : m_board->Drawings() ) + visitItem( drawing ); + + for( BOARD_ITEM* item : deleteList ) + m_board->Delete( item ); + + m_undefinedLayers.clear(); + } + return m_board; } @@ -976,17 +1058,8 @@ T PCB_PARSER::lookUpLayer( const M& aMap ) } #endif - wxString error = wxString::Format( _( - "Layer \"%s\" in file\n" - "\"%s\"\n" - "at line %d, position %d\n" - "was not defined in the layers section" - ), - GetChars( FROM_UTF8( CurText() ) ), - GetChars( CurSource() ), - CurLineNumber(), CurOffset() ); - - THROW_IO_ERROR( error ); + m_undefinedLayers.insert( curText ); + return Rescue; } return it->second; diff --git a/pcbnew/pcb_parser.h b/pcbnew/pcb_parser.h index 66ab78aca3..dca5de775f 100644 --- a/pcbnew/pcb_parser.h +++ b/pcbnew/pcb_parser.h @@ -70,6 +70,7 @@ class PCB_PARSER : public PCB_LEXER BOARD* m_board; LAYER_ID_MAP m_layerIndices; ///< map layer name to it's index LSET_MAP m_layerMasks; ///< map layer names to their masks + std::set m_undefinedLayers; ///< set of layers not defined in layers section std::vector m_netCodes; ///< net codes mapping for boards being loaded bool m_tooRecent; ///< true if version parses as later than supported int m_requiredVersion; ///< set to the KiCad format version this board requires