diff --git a/pcbnew/swig/pcbnew.i b/pcbnew/swig/pcbnew.i index 5aa67e2391..7adf509d98 100644 --- a/pcbnew/swig/pcbnew.i +++ b/pcbnew/swig/pcbnew.i @@ -124,6 +124,7 @@ HANDLE_EXCEPTIONS(PLUGIN::FootprintDelete) %include HANDLE_EXCEPTIONS(LoadBoard) +HANDLE_EXCEPTIONS(WriteDRCReport) %include diff --git a/pcbnew/swig/pcbnew_scripting_helpers.cpp b/pcbnew/swig/pcbnew_scripting_helpers.cpp index 1400be907f..a91836dc5c 100644 --- a/pcbnew/swig/pcbnew_scripting_helpers.cpp +++ b/pcbnew/swig/pcbnew_scripting_helpers.cpp @@ -31,15 +31,13 @@ #undef HAVE_CLOCK_GETTIME // macro is defined in Python.h and causes redefine warning #include -#include #include #include +#include +#include #include #include #include -#include -#include -#include #include #include #include @@ -112,7 +110,7 @@ BOARD* LoadBoard( wxString& aFileName, IO_MGR::PCB_FILE_T aFormat ) if( !project ) { GetSettingsManager()->LoadProject( projectPath ); - GetSettingsManager()->GetProject( projectPath ); + project = GetSettingsManager()->GetProject( projectPath ); } // Board cannot be loaded without a project, so create the default project @@ -307,3 +305,104 @@ bool IsActionRunning() { return ACTION_PLUGINS::IsActionRunning(); } + + +bool WriteDRCReport( BOARD* aBoard, const wxString& aFileName, EDA_UNITS aUnits, + bool aTestTracksAgainstZones, bool aReportAllTrackErrors ) +{ + wxCHECK( aBoard, false ); + + BOARD_DESIGN_SETTINGS& bds = aBoard->GetDesignSettings(); + std::shared_ptr engine = bds.m_DRCEngine; + + if( !engine ) + { + bds.m_DRCEngine = std::make_shared( aBoard, &bds ); + engine = bds.m_DRCEngine; + } + + wxCHECK( engine, false ); + + try + { + engine->InitEngine( s_SettingsManager->Prj().AbsolutePath( "drc-rules" ) ); + } + catch( PARSE_ERROR& pe ) + { + return false; + } + + std::vector> footprints; + std::vector> unconnected; + std::vector> violations; + + engine->SetProgressReporter( nullptr ); + + engine->SetViolationHandler( + [&]( const std::shared_ptr& aItem, wxPoint aPos ) + { + if( aItem->GetErrorCode() == DRCE_MISSING_FOOTPRINT + || aItem->GetErrorCode() == DRCE_DUPLICATE_FOOTPRINT + || aItem->GetErrorCode() == DRCE_EXTRA_FOOTPRINT + || aItem->GetErrorCode() == DRCE_NET_CONFLICT ) + { + footprints.push_back( aItem ); + } + else if( aItem->GetErrorCode() == DRCE_UNCONNECTED_ITEMS ) + { + unconnected.push_back( aItem ); + } + else + { + violations.push_back( aItem ); + } + } ); + + engine->RunTests( aUnits, aTestTracksAgainstZones, aReportAllTrackErrors, false ); + engine->ClearViolationHandler(); + + // TODO: Unify this with DIALOG_DRC::writeReport + + FILE* fp = wxFopen( aFileName, wxT( "w" ) ); + + if( fp == nullptr ) + return false; + + std::map itemMap; + aBoard->FillItemMap( itemMap ); + + fprintf( fp, "** Drc report for %s **\n", TO_UTF8( aBoard->GetFileName() ) ); + + wxDateTime now = wxDateTime::Now(); + + fprintf( fp, "** Created on %s **\n", TO_UTF8( now.Format( wxT( "%F %T" ) ) ) ); + + fprintf( fp, "\n** Found %d DRC violations **\n", static_cast( violations.size() ) ); + + for( const std::shared_ptr& item : violations ) + { + SEVERITY severity = static_cast( bds.GetSeverity( item->GetErrorCode() ) ); + fprintf( fp, "%s", TO_UTF8( item->ShowReport( aUnits, severity, itemMap ) ) ); + } + + fprintf( fp, "\n** Found %d unconnected pads **\n", static_cast( unconnected.size() ) ); + + for( const std::shared_ptr& item : unconnected ) + { + SEVERITY severity = static_cast( bds.GetSeverity( item->GetErrorCode() ) ); + fprintf( fp, "%s", TO_UTF8( item->ShowReport( aUnits, severity, itemMap ) ) ); + } + + fprintf( fp, "\n** Found %d Footprint errors **\n", static_cast( footprints.size() ) ); + + for( const std::shared_ptr& item : footprints ) + { + SEVERITY severity = static_cast( bds.GetSeverity( item->GetErrorCode() ) ); + fprintf( fp, "%s", TO_UTF8( item->ShowReport( aUnits, severity, itemMap ) ) ); + } + + fprintf( fp, "\n** End of Report **\n" ); + fclose( fp ); + + return true; +} diff --git a/pcbnew/swig/pcbnew_scripting_helpers.h b/pcbnew/swig/pcbnew_scripting_helpers.h index aa952a86d6..1d91993107 100644 --- a/pcbnew/swig/pcbnew_scripting_helpers.h +++ b/pcbnew/swig/pcbnew_scripting_helpers.h @@ -142,4 +142,20 @@ int GetUserUnits(); */ bool IsActionRunning(); +/** + * Runs the DRC check on the given board and writes the results to a report file. + * Requires that the project for the board be loaded, and note that unlike the DRC dialog + * this does not attempt to fill zones, so zones must be valid before calling. + * + * @param aBoard is a valid loaded board + * @param aFileName is the full path and name of the report file to write + * @param aUnits is the units to use in the report + * @param aTestTracksAgainstZones controls whether full track/zone checking is done (slow) + * @param aReportAllTrackErrors controls whether all errors or just the first error is reported + * for each track + * @return true if successful, false if not + */ +bool WriteDRCReport( BOARD* aBoard, const wxString& aFileName, EDA_UNITS aUnits, + bool aTestTracksAgainstZones, bool aReportAllTrackErrors ); + #endif // __PCBNEW_SCRIPTING_HELPERS_H