From 1333c4c305400cd63d4d789d9317c4d9f77feb55 Mon Sep 17 00:00:00 2001 From: Jeff Young <jeff@rokeby.ie> Date: Sun, 16 Mar 2025 17:26:45 +0000 Subject: [PATCH] Move layer arg parsing up so we can handle user-defined layer names. Fixes https://gitlab.com/kicad/code/kicad/-/issues/18773 --- common/jobs/job_export_pcb_plot.h | 4 + kicad/cli/command_fp_export_svg.cpp | 17 +--- kicad/cli/command_pcb_export_base.cpp | 115 +++-------------------- kicad/cli/command_pcb_export_base.h | 20 +--- kicad/cli/command_pcb_export_dxf.cpp | 27 +----- kicad/cli/command_pcb_export_gencad.cpp | 16 +--- kicad/cli/command_pcb_export_gerber.cpp | 29 ++---- kicad/cli/command_pcb_export_gerbers.cpp | 30 +----- kicad/cli/command_pcb_export_ipc2581.cpp | 9 +- kicad/cli/command_pcb_export_ipcd356.cpp | 12 +-- kicad/cli/command_pcb_export_odb.cpp | 11 +-- kicad/cli/command_pcb_export_pdf.cpp | 27 +----- kicad/cli/command_pcb_export_pos.cpp | 11 +-- kicad/cli/command_pcb_export_svg.cpp | 27 +----- pcbnew/pcbnew_jobs_handler.cpp | 112 ++++++++++++++++++++++ pcbnew/pcbnew_jobs_handler.h | 2 + 16 files changed, 166 insertions(+), 303 deletions(-) diff --git a/common/jobs/job_export_pcb_plot.h b/common/jobs/job_export_pcb_plot.h index 1a4c22ee54..2a25b641fa 100644 --- a/common/jobs/job_export_pcb_plot.h +++ b/common/jobs/job_export_pcb_plot.h @@ -42,6 +42,10 @@ public: JOB_EXPORT_PCB_PLOT( PLOT_FORMAT aFormat, const std::string& aType, bool aOutputIsDirectory ); +public: + wxString m_argLayers; + wxString m_argCommonLayers; + PLOT_FORMAT m_plotFormat; wxString m_filename; diff --git a/kicad/cli/command_fp_export_svg.cpp b/kicad/cli/command_fp_export_svg.cpp index b2b12a996c..6bf565550d 100644 --- a/kicad/cli/command_fp_export_svg.cpp +++ b/kicad/cli/command_fp_export_svg.cpp @@ -22,13 +22,11 @@ #include <cli/exit_codes.h> #include "jobs/job_fp_export_svg.h" #include <kiface_base.h> -#include <layer_ids.h> #include <string_utils.h> #include <wx/crt.h> #include <wx/dir.h> #include <macros.h> -#include <wx/tokenzr.h> #define ARG_FOOTPRINT "--footprint" @@ -38,7 +36,7 @@ CLI::FP_EXPORT_SVG_COMMAND::FP_EXPORT_SVG_COMMAND() : m_argParser.add_description( UTF8STDSTR( _( "Exports the footprint or entire footprint " "library to SVG" ) ) ); - addLayerArg( false ); + addLayerArg(); addDefineArg(); m_argParser.add_argument( "-t", ARG_THEME ) @@ -75,10 +73,6 @@ CLI::FP_EXPORT_SVG_COMMAND::FP_EXPORT_SVG_COMMAND() : int CLI::FP_EXPORT_SVG_COMMAND::doPerform( KIWAY& aKiway ) { - int baseExit = PCB_EXPORT_BASE_COMMAND::doPerform( aKiway ); - if( baseExit != EXIT_CODES::OK ) - return baseExit; - std::unique_ptr<JOB_FP_EXPORT_SVG> svgJob = std::make_unique<JOB_FP_EXPORT_SVG>(); svgJob->m_libraryPath = m_argInput; @@ -99,12 +93,7 @@ int CLI::FP_EXPORT_SVG_COMMAND::doPerform( KIWAY& aKiway ) svgJob->m_colorTheme = From_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() ); - if( !m_selectedLayers.empty() ) - svgJob->m_plotLayerSequence = m_selectedLayers; - else - svgJob->m_plotLayerSequence = LSET::AllLayersMask().SeqStackupForPlotting(); + svgJob->m_argLayers = From_UTF8( m_argParser.get<std::string>( ARG_LAYERS ).c_str() ); - int exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, svgJob.get() ); - - return exitCode; + return aKiway.ProcessJob( KIWAY::FACE_PCB, svgJob.get() ); } diff --git a/kicad/cli/command_pcb_export_base.cpp b/kicad/cli/command_pcb_export_base.cpp index 45ebdd741e..3667d4950d 100644 --- a/kicad/cli/command_pcb_export_base.cpp +++ b/kicad/cli/command_pcb_export_base.cpp @@ -19,126 +19,33 @@ */ #include "command_pcb_export_base.h" -#include <cli/exit_codes.h> -#include <kiface_base.h> #include <bitset> -#include <layer_ids.h> -#include <lset.h> -#include <lseq.h> #include <string_utils.h> -#include <macros.h> -#include <wx/tokenzr.h> -#include <wx/crt.h> CLI::PCB_EXPORT_BASE_COMMAND::PCB_EXPORT_BASE_COMMAND( const std::string& aName, - bool aInputCanBeDir, - bool aOutputIsDir ) : + bool aInputCanBeDir, bool aOutputIsDir ) : COMMAND( aName ) { - m_selectedLayersSet = false; - m_requireLayers = false; - m_hasLayerArg = false; - addCommonArgs( true, true, aInputCanBeDir, aOutputIsDir ); - - // Build list of layer names and their layer mask: - for( int layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer ) - { - std::string untranslated = TO_UTF8( wxString( LSET::Name( PCB_LAYER_ID( layer ) ) ) ); - - //m_layerIndices[untranslated] = PCB_LAYER_ID( layer ); - - // Add layer name used in pcb files - m_layerMasks[untranslated] = LSET( { PCB_LAYER_ID( layer ) } ); - // Add layer name using GUI canonical layer name - m_layerGuiMasks[ TO_UTF8(LayerName( layer ) ) ] = LSET( { PCB_LAYER_ID( layer ) } ); - } - - // Add list of grouped layer names used in pcb files - m_layerMasks["*"] = LSET::AllLayersMask(); - m_layerMasks["*.Cu"] = LSET::AllCuMask(); - m_layerMasks["*In.Cu"] = LSET::InternalCuMask(); - m_layerMasks["F&B.Cu"] = LSET( { F_Cu, B_Cu } ); - m_layerMasks["*.Adhes"] = LSET( { B_Adhes, F_Adhes } ); - m_layerMasks["*.Paste"] = LSET( { B_Paste, F_Paste } ); - m_layerMasks["*.Mask"] = LSET( { B_Mask, F_Mask } ); - m_layerMasks["*.SilkS"] = LSET( { B_SilkS, F_SilkS } ); - m_layerMasks["*.Fab"] = LSET( { B_Fab, F_Fab } ); - m_layerMasks["*.CrtYd"] = LSET( { B_CrtYd, F_CrtYd } ); - - // Add list of grouped layer names using GUI canonical layer names - m_layerGuiMasks["*.Adhesive"] = LSET( { B_Adhes, F_Adhes } ); - m_layerGuiMasks["*.Silkscreen"] = LSET( { B_SilkS, F_SilkS } ); - m_layerGuiMasks["*.Courtyard"] = LSET( { B_CrtYd, F_CrtYd } ); } -LSEQ CLI::PCB_EXPORT_BASE_COMMAND::convertLayerStringList( wxString& aLayerString ) const -{ - LSEQ layerMask; - - if( !aLayerString.IsEmpty() ) - { - wxStringTokenizer layerTokens( aLayerString, "," ); - - while( layerTokens.HasMoreTokens() ) - { - std::string token = TO_UTF8( layerTokens.GetNextToken() ); - - // Search for a layer name in canonical layer name used in .kicad_pcb files: - if( m_layerMasks.count( token ) ) - { - for( PCB_LAYER_ID layer : m_layerMasks.at( token ).Seq() ) - layerMask.push_back( layer ); - } - // Search for a layer name in canonical layer name used in GUI (not translated): - else if( m_layerGuiMasks.count( token ) ) - { - for( PCB_LAYER_ID layer : m_layerGuiMasks.at( token ).Seq() ) - layerMask.push_back( layer ); - } - else - { - wxFprintf( stderr, _( "Invalid layer name \"%s\"\n" ), token ); - } - } - } - - return layerMask; -} - - -void CLI::PCB_EXPORT_BASE_COMMAND::addLayerArg( bool aRequire ) +void CLI::PCB_EXPORT_BASE_COMMAND::addLayerArg() { m_argParser.add_argument( "-l", ARG_LAYERS ) .default_value( std::string() ) - .help( UTF8STDSTR( - _( "Comma separated list of untranslated layer names to include such as " - "F.Cu,B.Cu" ) ) ) + .help( UTF8STDSTR( _( "Comma separated list of untranslated layer names to include " + "such as F.Cu,B.Cu" ) ) ) .metavar( "LAYER_LIST" ); - - m_hasLayerArg = true; - m_requireLayers = aRequire; } -int CLI::PCB_EXPORT_BASE_COMMAND::doPerform( KIWAY& aKiway ) +void CLI::PCB_EXPORT_BASE_COMMAND::addCommonLayersArg() { - if( m_hasLayerArg ) - { - wxString layers = From_UTF8( m_argParser.get<std::string>( ARG_LAYERS ).c_str() ); - - LSEQ layerMask = convertLayerStringList( layers ); - - if( m_requireLayers && layerMask.size() < 1 ) - { - wxFprintf( stderr, _( "At least one layer must be specified\n" ) ); - return EXIT_CODES::ERR_ARGS; - } - - m_selectedLayers = layerMask; - } - - return EXIT_CODES::OK; -} + m_argParser.add_argument( "--cl", ARG_COMMON_LAYERS ) + .default_value( std::string() ) + .help( UTF8STDSTR( _( "Layers to include on each plot, comma separated list of " + "untranslated layer names to include such as F.Cu,B.Cu" ) ) ) + .metavar( "COMMON_LAYER_LIST" ); +} \ No newline at end of file diff --git a/kicad/cli/command_pcb_export_base.h b/kicad/cli/command_pcb_export_base.h index 6e48d135dc..5f9d58583d 100644 --- a/kicad/cli/command_pcb_export_base.h +++ b/kicad/cli/command_pcb_export_base.h @@ -22,9 +22,6 @@ #define COMMAND_EXPORT_PCB_BASE_H #include "command.h" -#include <layer_ids.h> -#include <lset.h> -#include <lseq.h> namespace CLI { @@ -74,21 +71,8 @@ struct PCB_EXPORT_BASE_COMMAND : public COMMAND bool aOutputIsDir = false ); protected: - int doPerform( KIWAY& aKiway ) override; - LSEQ convertLayerStringList( wxString& aLayerString ) const; - void addLayerArg( bool aRequire ); - - // The list of canonical layer names used in .kicad_pcb files: - std::map<std::string, LSET> m_layerMasks; - - // The list of canonical layer names used in GUI (not translated): - std::map<std::string, LSET> m_layerGuiMasks; - - LSEQ m_selectedLayers; - bool m_selectedLayersSet; - - bool m_hasLayerArg; - bool m_requireLayers; + void addLayerArg(); + void addCommonLayersArg(); }; } // namespace CLI diff --git a/kicad/cli/command_pcb_export_dxf.cpp b/kicad/cli/command_pcb_export_dxf.cpp index 2a948dcd47..195b1896d1 100644 --- a/kicad/cli/command_pcb_export_dxf.cpp +++ b/kicad/cli/command_pcb_export_dxf.cpp @@ -22,13 +22,10 @@ #include <cli/exit_codes.h> #include "jobs/job_export_pcb_dxf.h" #include <kiface_base.h> -#include <layer_ids.h> #include <string_utils.h> #include <wx/crt.h> #include <macros.h> -#include <wx/tokenzr.h> - #include <locale_io.h> #define ARG_USE_CONTOURS "--use-contours" @@ -42,7 +39,8 @@ CLI::PCB_EXPORT_DXF_COMMAND::PCB_EXPORT_DXF_COMMAND() : { m_argParser.add_description( UTF8STDSTR( _( "Generate a DXF from a list of layers" ) ) ); - addLayerArg( true ); + addLayerArg(); + addCommonLayersArg(); addDrawingSheetArg(); addDefineArg(); @@ -96,13 +94,6 @@ CLI::PCB_EXPORT_DXF_COMMAND::PCB_EXPORT_DXF_COMMAND() : .scan<'i', int>() .default_value( 2 ); - m_argParser.add_argument( "--cl", ARG_COMMON_LAYERS ) - .default_value( std::string() ) - .help( UTF8STDSTR( - _( "Layers to include on each plot, comma separated list of untranslated " - "layer names to include such as F.Cu,B.Cu" ) ) ) - .metavar( "COMMON_LAYER_LIST" ); - m_argParser.add_argument( ARG_MODE_SINGLE ) .help( UTF8STDSTR( _( "Generates a single file with the output arg path acting as the complete " @@ -124,10 +115,6 @@ CLI::PCB_EXPORT_DXF_COMMAND::PCB_EXPORT_DXF_COMMAND() : int CLI::PCB_EXPORT_DXF_COMMAND::doPerform( KIWAY& aKiway ) { - int baseExit = PCB_EXPORT_BASE_COMMAND::doPerform( aKiway ); - if( baseExit != EXIT_CODES::OK ) - return baseExit; - std::unique_ptr<JOB_EXPORT_PCB_DXF> dxfJob( new JOB_EXPORT_PCB_DXF() ); dxfJob->m_filename = m_argInput; @@ -175,10 +162,8 @@ int CLI::PCB_EXPORT_DXF_COMMAND::doPerform( KIWAY& aKiway ) return EXIT_CODES::ERR_ARGS; } - dxfJob->m_plotLayerSequence = m_selectedLayers; - - wxString layers = From_UTF8( m_argParser.get<std::string>( ARG_COMMON_LAYERS ).c_str() ); - dxfJob->m_plotOnAllLayersSequence = convertLayerStringList( layers ); + dxfJob->m_argLayers = From_UTF8( m_argParser.get<std::string>( ARG_LAYERS ).c_str() ); + dxfJob->m_argCommonLayers = From_UTF8( m_argParser.get<std::string>( ARG_COMMON_LAYERS ).c_str() ); if( m_argParser.get<bool>( ARG_MODE_MULTI ) ) dxfJob->m_genMode = JOB_EXPORT_PCB_DXF::GEN_MODE::MULTI; @@ -196,7 +181,5 @@ int CLI::PCB_EXPORT_DXF_COMMAND::doPerform( KIWAY& aKiway ) LOCALE_IO dummy; // Switch to "C" locale - int exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, dxfJob.get() ); - - return exitCode; + return aKiway.ProcessJob( KIWAY::FACE_PCB, dxfJob.get() ); } diff --git a/kicad/cli/command_pcb_export_gencad.cpp b/kicad/cli/command_pcb_export_gencad.cpp index 2b64535356..1ec08d10a9 100644 --- a/kicad/cli/command_pcb_export_gencad.cpp +++ b/kicad/cli/command_pcb_export_gencad.cpp @@ -22,21 +22,16 @@ #include <cli/exit_codes.h> #include "jobs/job_export_pcb_gencad.h" #include <kiface_base.h> -#include <layer_ids.h> #include <string_utils.h> #include <wx/crt.h> -#include <macros.h> -#include <wx/tokenzr.h> - #include <locale_io.h> CLI::PCB_EXPORT_GENCAD_COMMAND::PCB_EXPORT_GENCAD_COMMAND() : PCB_EXPORT_BASE_COMMAND( "gencad", false, true ) { - // TODO: Update string to remove reference to layers - m_argParser.add_description( UTF8STDSTR( _( "Generate Gencad from a list of layers" ) ) ); + m_argParser.add_description( UTF8STDSTR( _( "Export the PCB in Gencad format" ) ) ); addDefineArg(); @@ -70,11 +65,6 @@ CLI::PCB_EXPORT_GENCAD_COMMAND::PCB_EXPORT_GENCAD_COMMAND() : int CLI::PCB_EXPORT_GENCAD_COMMAND::doPerform( KIWAY& aKiway ) { - int baseExit = PCB_EXPORT_BASE_COMMAND::doPerform( aKiway ); - - if( baseExit != EXIT_CODES::OK ) - return baseExit; - std::unique_ptr<JOB_EXPORT_PCB_GENCAD> gencadJob( new JOB_EXPORT_PCB_GENCAD() ); gencadJob->m_filename = m_argInput; @@ -94,7 +84,5 @@ int CLI::PCB_EXPORT_GENCAD_COMMAND::doPerform( KIWAY& aKiway ) } LOCALE_IO dummy; // Switch to "C" locale - int exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, gencadJob.get() ); - - return exitCode; + return aKiway.ProcessJob( KIWAY::FACE_PCB, gencadJob.get() ); } diff --git a/kicad/cli/command_pcb_export_gerber.cpp b/kicad/cli/command_pcb_export_gerber.cpp index c76fc5b9a5..b7c8a51e00 100644 --- a/kicad/cli/command_pcb_export_gerber.cpp +++ b/kicad/cli/command_pcb_export_gerber.cpp @@ -22,12 +22,9 @@ #include <cli/exit_codes.h> #include "jobs/job_export_pcb_gerber.h" #include <kiface_base.h> -#include <layer_ids.h> #include <wx/crt.h> #include <macros.h> -#include <wx/tokenzr.h> - #include <locale_io.h> #include <string_utils.h> @@ -35,7 +32,8 @@ CLI::PCB_EXPORT_GERBER_COMMAND::PCB_EXPORT_GERBER_COMMAND( const std::string& aName ) : PCB_EXPORT_BASE_COMMAND( aName ) { - addLayerArg( true ); + addLayerArg(); + addCommonLayersArg(); addDrawingSheetArg(); addDefineArg(); @@ -90,13 +88,6 @@ CLI::PCB_EXPORT_GERBER_COMMAND::PCB_EXPORT_GERBER_COMMAND( const std::string& aN .help( UTF8STDSTR( _( "Use drill/place file origin" ) ) ) .flag(); - m_argParser.add_argument( "--cl", ARG_COMMON_LAYERS ) - .default_value( std::string() ) - .help( UTF8STDSTR( - _( "Layers to include on each plot, comma separated list of untranslated " - "layer names to include such as F.Cu,B.Cu" ) ) ) - .metavar( "COMMON_LAYER_LIST" ); - m_argParser.add_argument( ARG_PRECISION ) .help( UTF8STDSTR( _( "Precision of Gerber coordinates, valid options: 5 or 6" ) ) ) .scan<'i', int>() @@ -140,10 +131,9 @@ int CLI::PCB_EXPORT_GERBER_COMMAND::populateJob( JOB_EXPORT_PCB_GERBER* aJob ) aJob->m_useDrillOrigin = m_argParser.get<bool>( ARG_USE_DRILL_FILE_ORIGIN ); aJob->m_useProtelFileExtension = !m_argParser.get<bool>( ARG_NO_PROTEL_EXTENSION ); aJob->m_precision = m_argParser.get<int>( ARG_PRECISION ); - aJob->m_plotLayerSequence = m_selectedLayers; - wxString layers = From_UTF8( m_argParser.get<std::string>( ARG_COMMON_LAYERS ).c_str() ); - aJob->m_plotOnAllLayersSequence = convertLayerStringList( layers ); + aJob->m_argLayers = From_UTF8( m_argParser.get<std::string>( ARG_LAYERS ).c_str() ); + aJob->m_argCommonLayers = From_UTF8( m_argParser.get<std::string>( ARG_COMMON_LAYERS ).c_str() ); if( m_argParser.get<bool>( DEPRECATED_ARG_PLOT_INVISIBLE_TEXT ) ) wxFprintf( stdout, DEPRECATED_ARD_PLOT_INVISIBLE_TEXT_WARNING ); @@ -169,20 +159,13 @@ int CLI::PCB_EXPORT_GERBER_COMMAND::doPerform( KIWAY& aKiway ) wxFprintf( stdout, wxT( "\033[33;1m%s\033[0m\n" ), _( "This command is deprecated as of KiCad 9.0, please use \"gerbers\" instead\n" ) ); - int exitCode = PCB_EXPORT_BASE_COMMAND::doPerform( aKiway ); - - if( exitCode != EXIT_CODES::OK ) - return exitCode; - std::unique_ptr<JOB_EXPORT_PCB_GERBER> gerberJob( new JOB_EXPORT_PCB_GERBER() ); - exitCode = populateJob( gerberJob.get() ); + int exitCode = populateJob( gerberJob.get() ); if( exitCode != EXIT_CODES::OK ) return exitCode; LOCALE_IO dummy; - exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, gerberJob.get() ); - - return exitCode; + return aKiway.ProcessJob( KIWAY::FACE_PCB, gerberJob.get() ); } diff --git a/kicad/cli/command_pcb_export_gerbers.cpp b/kicad/cli/command_pcb_export_gerbers.cpp index 694f87d4d8..9e669a4cf5 100644 --- a/kicad/cli/command_pcb_export_gerbers.cpp +++ b/kicad/cli/command_pcb_export_gerbers.cpp @@ -22,12 +22,7 @@ #include <cli/exit_codes.h> #include "jobs/job_export_pcb_gerbers.h" #include <kiface_base.h> -#include <layer_ids.h> #include <string_utils.h> -#include <wx/crt.h> - -#include <macros.h> -#include <wx/tokenzr.h> #include <locale_io.h> @@ -37,19 +32,11 @@ CLI::PCB_EXPORT_GERBERS_COMMAND::PCB_EXPORT_GERBERS_COMMAND() : PCB_EXPORT_GERBER_COMMAND( "gerbers" ) { - m_requireLayers = false; + addCommonLayersArg(); m_argParser.add_description( UTF8STDSTR( _( "Plot multiple Gerbers for a PCB, including the " "ability to use stored board plot settings" ) ) ); - m_argParser.add_argument( "--cl", ARG_COMMON_LAYERS ) - .default_value( std::string() ) - .help( UTF8STDSTR( - _( "Layers to include on each plot, comma separated list of untranslated " - "layer names to include such as " - "F.Cu,B.Cu" ) ) ) - .metavar( "COMMON_LAYER_LIST" ); - m_argParser.add_argument( ARG_USE_BOARD_PLOT_PARAMS ) .help( UTF8STDSTR( _( "Use the Gerber plot settings already configured in the " "board file" ) ) ) @@ -59,24 +46,17 @@ CLI::PCB_EXPORT_GERBERS_COMMAND::PCB_EXPORT_GERBERS_COMMAND() : int CLI::PCB_EXPORT_GERBERS_COMMAND::doPerform( KIWAY& aKiway ) { - int exitCode = PCB_EXPORT_BASE_COMMAND::doPerform( aKiway ); - - if( exitCode != EXIT_CODES::OK ) - return exitCode; - std::unique_ptr<JOB_EXPORT_PCB_GERBERS> gerberJob( new JOB_EXPORT_PCB_GERBERS() ); - exitCode = populateJob( gerberJob.get() ); + int exitCode = populateJob( gerberJob.get() ); if( exitCode != EXIT_CODES::OK ) return exitCode; - wxString layers = From_UTF8( m_argParser.get<std::string>( ARG_COMMON_LAYERS ).c_str() ); - gerberJob->m_plotOnAllLayersSequence = convertLayerStringList( layers ); + gerberJob->m_argLayers = From_UTF8( m_argParser.get<std::string>( ARG_LAYERS ).c_str() ); + gerberJob->m_argCommonLayers = From_UTF8( m_argParser.get<std::string>( ARG_COMMON_LAYERS ).c_str() ); gerberJob->m_useBoardPlotParams = m_argParser.get<bool>( ARG_USE_BOARD_PLOT_PARAMS ); LOCALE_IO dummy; - exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, gerberJob.get() ); - - return exitCode; + return aKiway.ProcessJob( KIWAY::FACE_PCB, gerberJob.get() ); } diff --git a/kicad/cli/command_pcb_export_ipc2581.cpp b/kicad/cli/command_pcb_export_ipc2581.cpp index 549cf7756b..35851367df 100644 --- a/kicad/cli/command_pcb_export_ipc2581.cpp +++ b/kicad/cli/command_pcb_export_ipc2581.cpp @@ -102,11 +102,6 @@ CLI::PCB_EXPORT_IPC2581_COMMAND::PCB_EXPORT_IPC2581_COMMAND() : int CLI::PCB_EXPORT_IPC2581_COMMAND::doPerform( KIWAY& aKiway ) { - int exitCode = PCB_EXPORT_BASE_COMMAND::doPerform( aKiway ); - - if( exitCode != EXIT_CODES::OK ) - return exitCode; - std::unique_ptr<JOB_EXPORT_PCB_IPC2581> ipc2581Job( new JOB_EXPORT_PCB_IPC2581() ); ipc2581Job->m_filename = m_argInput; @@ -146,7 +141,5 @@ int CLI::PCB_EXPORT_IPC2581_COMMAND::doPerform( KIWAY& aKiway ) From_UTF8( m_argParser.get<std::string>( ARG_BOM_COL_DIST ).c_str() ); LOCALE_IO dummy; - exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, ipc2581Job.get() ); - - return exitCode; + return aKiway.ProcessJob( KIWAY::FACE_PCB, ipc2581Job.get() ); } diff --git a/kicad/cli/command_pcb_export_ipcd356.cpp b/kicad/cli/command_pcb_export_ipcd356.cpp index 02046d83be..e1d8d06827 100644 --- a/kicad/cli/command_pcb_export_ipcd356.cpp +++ b/kicad/cli/command_pcb_export_ipcd356.cpp @@ -25,9 +25,6 @@ #include <string_utils.h> #include <wx/crt.h> -#include <macros.h> -#include <wx/tokenzr.h> - #include <locale_io.h> CLI::PCB_EXPORT_IPCD356_COMMAND::PCB_EXPORT_IPCD356_COMMAND() : @@ -39,11 +36,6 @@ CLI::PCB_EXPORT_IPCD356_COMMAND::PCB_EXPORT_IPCD356_COMMAND() : int CLI::PCB_EXPORT_IPCD356_COMMAND::doPerform( KIWAY& aKiway ) { - int exitCode = PCB_EXPORT_BASE_COMMAND::doPerform( aKiway ); - - if( exitCode != EXIT_CODES::OK ) - return exitCode; - std::unique_ptr<JOB_EXPORT_PCB_IPCD356> ipcd356Job( new JOB_EXPORT_PCB_IPCD356() ); ipcd356Job->m_filename = m_argInput; @@ -55,7 +47,5 @@ int CLI::PCB_EXPORT_IPCD356_COMMAND::doPerform( KIWAY& aKiway ) return EXIT_CODES::ERR_INVALID_INPUT_FILE; } - exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, ipcd356Job.get() ); - - return exitCode; + return aKiway.ProcessJob( KIWAY::FACE_PCB, ipcd356Job.get() ); } diff --git a/kicad/cli/command_pcb_export_odb.cpp b/kicad/cli/command_pcb_export_odb.cpp index ae55f309e8..9f6772743d 100644 --- a/kicad/cli/command_pcb_export_odb.cpp +++ b/kicad/cli/command_pcb_export_odb.cpp @@ -25,8 +25,6 @@ #include <wx/crt.h> #include <macros.h> -#include <wx/tokenzr.h> - #include <locale_io.h> #define ARG_COMPRESS "--compression" @@ -60,11 +58,6 @@ CLI::PCB_EXPORT_ODB_COMMAND::PCB_EXPORT_ODB_COMMAND() : int CLI::PCB_EXPORT_ODB_COMMAND::doPerform( KIWAY& aKiway ) { - int exitCode = PCB_EXPORT_BASE_COMMAND::doPerform( aKiway ); - - if( exitCode != EXIT_CODES::OK ) - return exitCode; - std::unique_ptr<JOB_EXPORT_PCB_ODB> job( new JOB_EXPORT_PCB_ODB() ); job->m_filename = m_argInput; @@ -97,7 +90,5 @@ int CLI::PCB_EXPORT_ODB_COMMAND::doPerform( KIWAY& aKiway ) job->m_compressionMode = JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::NONE; LOCALE_IO dummy; - exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, job.get() ); - - return exitCode; + return aKiway.ProcessJob( KIWAY::FACE_PCB, job.get() ); } diff --git a/kicad/cli/command_pcb_export_pdf.cpp b/kicad/cli/command_pcb_export_pdf.cpp index fac73b0d5c..8a3320c083 100644 --- a/kicad/cli/command_pcb_export_pdf.cpp +++ b/kicad/cli/command_pcb_export_pdf.cpp @@ -22,7 +22,6 @@ #include <cli/exit_codes.h> #include "jobs/job_export_pcb_pdf.h" #include <kiface_base.h> -#include <layer_ids.h> #include <string_utils.h> #include <wx/crt.h> @@ -37,7 +36,8 @@ CLI::PCB_EXPORT_PDF_COMMAND::PCB_EXPORT_PDF_COMMAND() : { m_argParser.add_description( UTF8STDSTR( _( "Generate PDF from a list of layers" ) ) ); - addLayerArg( true ); + addLayerArg(); + addCommonLayersArg(); addDrawingSheetArg(); addDefineArg(); @@ -95,14 +95,6 @@ CLI::PCB_EXPORT_PDF_COMMAND::PCB_EXPORT_PDF_COMMAND() : .scan<'i', int>() .default_value( 2 ); - m_argParser.add_argument( "--cl", ARG_COMMON_LAYERS ) - .default_value( std::string() ) - .help( UTF8STDSTR( - _( "Layers to include on each plot, comma separated list of untranslated " - "layer names to include such as " - "F.Cu,B.Cu" ) ) ) - .metavar( "COMMON_LAYER_LIST" ); - m_argParser.add_argument( DEPRECATED_ARG_PLOT_INVISIBLE_TEXT ) .help( UTF8STDSTR( _( DEPRECATED_ARG_PLOT_INVISIBLE_TEXT_DESC ) ) ) .flag(); @@ -126,11 +118,6 @@ CLI::PCB_EXPORT_PDF_COMMAND::PCB_EXPORT_PDF_COMMAND() : int CLI::PCB_EXPORT_PDF_COMMAND::doPerform( KIWAY& aKiway ) { - int baseExit = PCB_EXPORT_BASE_COMMAND::doPerform( aKiway ); - - if( baseExit != EXIT_CODES::OK ) - return baseExit; - std::unique_ptr<JOB_EXPORT_PCB_PDF> pdfJob( new JOB_EXPORT_PCB_PDF() ); pdfJob->m_filename = m_argInput; @@ -166,8 +153,6 @@ int CLI::PCB_EXPORT_PDF_COMMAND::doPerform( KIWAY& aKiway ) int drillShape = m_argParser.get<int>( ARG_DRILL_SHAPE_OPTION ); pdfJob->m_drillShapeOption = static_cast<JOB_EXPORT_PCB_PDF::DRILL_MARKS>( drillShape ); - pdfJob->m_plotLayerSequence = m_selectedLayers; - bool argModeMulti = m_argParser.get<bool>( ARG_MODE_MULTIPAGE ); bool argModeSeparate = m_argParser.get<bool>( ARG_MODE_SEPARATE ); bool argModeSingle = m_argParser.get<bool>( ARG_MODE_SINGLE ); @@ -178,8 +163,8 @@ int CLI::PCB_EXPORT_PDF_COMMAND::doPerform( KIWAY& aKiway ) return EXIT_CODES::ERR_ARGS; } - wxString layers = From_UTF8( m_argParser.get<std::string>( ARG_COMMON_LAYERS ).c_str() ); - pdfJob->m_plotOnAllLayersSequence = convertLayerStringList( layers ); + pdfJob->m_argLayers = From_UTF8( m_argParser.get<std::string>( ARG_LAYERS ).c_str() ); + pdfJob->m_argCommonLayers = From_UTF8( m_argParser.get<std::string>( ARG_COMMON_LAYERS ).c_str() ); if( argModeMulti ) pdfJob->m_pdfGenMode = JOB_EXPORT_PCB_PDF::GEN_MODE::ONE_PAGE_PER_LAYER_ONE_FILE; @@ -189,7 +174,5 @@ int CLI::PCB_EXPORT_PDF_COMMAND::doPerform( KIWAY& aKiway ) pdfJob->m_pdfGenMode = JOB_EXPORT_PCB_PDF::GEN_MODE::ALL_LAYERS_ONE_FILE; LOCALE_IO dummy; // Switch to "C" locale - int exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, pdfJob.get() ); - - return exitCode; + return aKiway.ProcessJob( KIWAY::FACE_PCB, pdfJob.get() ); } diff --git a/kicad/cli/command_pcb_export_pos.cpp b/kicad/cli/command_pcb_export_pos.cpp index d2f4b8a87d..28c59bc031 100644 --- a/kicad/cli/command_pcb_export_pos.cpp +++ b/kicad/cli/command_pcb_export_pos.cpp @@ -22,7 +22,6 @@ #include <cli/exit_codes.h> #include "jobs/job_export_pcb_pos.h" #include <kiface_base.h> -#include <layer_ids.h> #include <string_utils.h> #include <wx/crt.h> @@ -92,11 +91,6 @@ CLI::PCB_EXPORT_POS_COMMAND::PCB_EXPORT_POS_COMMAND() : int CLI::PCB_EXPORT_POS_COMMAND::doPerform( KIWAY& aKiway ) { - int baseExit = PCB_EXPORT_BASE_COMMAND::doPerform( aKiway ); - - if( baseExit != EXIT_CODES::OK ) - return baseExit; - std::unique_ptr<JOB_EXPORT_PCB_POS> aPosJob( new JOB_EXPORT_PCB_POS() ); aPosJob->m_filename = m_argInput; @@ -179,9 +173,6 @@ int CLI::PCB_EXPORT_POS_COMMAND::doPerform( KIWAY& aKiway ) return EXIT_CODES::ERR_ARGS; } - LOCALE_IO dummy; - int exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, aPosJob.get() ); - - return exitCode; + return aKiway.ProcessJob( KIWAY::FACE_PCB, aPosJob.get() ); } diff --git a/kicad/cli/command_pcb_export_svg.cpp b/kicad/cli/command_pcb_export_svg.cpp index b59f8963b2..6bb196e5ef 100644 --- a/kicad/cli/command_pcb_export_svg.cpp +++ b/kicad/cli/command_pcb_export_svg.cpp @@ -24,7 +24,6 @@ #include "command_pcb_export_base.h" #include "jobs/job_export_pcb_svg.h" #include <kiface_base.h> -#include <layer_ids.h> #include <string_utils.h> #include <regex> #include <wx/crt.h> @@ -41,7 +40,8 @@ CLI::PCB_EXPORT_SVG_COMMAND::PCB_EXPORT_SVG_COMMAND() : { m_argParser.add_description( UTF8STDSTR( _( "Generate SVG outputs of a given layer list" ) ) ); - addLayerArg( true ); + addLayerArg(); + addCommonLayersArg(); addDrawingSheetArg(); addDefineArg(); @@ -103,15 +103,6 @@ CLI::PCB_EXPORT_SVG_COMMAND::PCB_EXPORT_SVG_COMMAND() : .default_value( 2 ) .metavar( "SHAPE_OPTION" ); - m_argParser.add_argument( "--cl", ARG_COMMON_LAYERS ) - .default_value( std::string() ) - .help( UTF8STDSTR( - _( "Layers to include on each plot, comma separated list of untranslated " - "layer names to include such as " - "F.Cu,B.Cu" ) ) ) - .metavar( "COMMON_LAYER_LIST" ); - - m_argParser.add_argument( ARG_MODE_SINGLE ) .help( UTF8STDSTR( _( "Generates a single file with the output arg path acting as the complete " @@ -133,10 +124,6 @@ CLI::PCB_EXPORT_SVG_COMMAND::PCB_EXPORT_SVG_COMMAND() : int CLI::PCB_EXPORT_SVG_COMMAND::doPerform( KIWAY& aKiway ) { - int baseExit = PCB_EXPORT_BASE_COMMAND::doPerform( aKiway ); - if( baseExit != EXIT_CODES::OK ) - return baseExit; - std::unique_ptr<JOB_EXPORT_PCB_SVG> svgJob( new JOB_EXPORT_PCB_SVG() ); svgJob->m_mirror = m_argParser.get<bool>( ARG_MIRROR ); @@ -179,8 +166,8 @@ int CLI::PCB_EXPORT_SVG_COMMAND::doPerform( KIWAY& aKiway ) svgJob->m_plotDrawingSheet = !m_argParser.get<bool>( ARG_EXCLUDE_DRAWING_SHEET ); svgJob->SetVarOverrides( m_argDefineVars ); - wxString layers = From_UTF8( m_argParser.get<std::string>( ARG_COMMON_LAYERS ).c_str() ); - svgJob->m_plotOnAllLayersSequence = convertLayerStringList( layers ); + svgJob->m_argLayers = From_UTF8( m_argParser.get<std::string>( ARG_LAYERS ).c_str() ); + svgJob->m_argCommonLayers = From_UTF8( m_argParser.get<std::string>( ARG_COMMON_LAYERS ).c_str() ); if( !wxFile::Exists( svgJob->m_filename ) ) { @@ -188,8 +175,6 @@ int CLI::PCB_EXPORT_SVG_COMMAND::doPerform( KIWAY& aKiway ) return EXIT_CODES::ERR_INVALID_INPUT_FILE; } - svgJob->m_plotLayerSequence = m_selectedLayers; - if( m_argParser.get<bool>( ARG_MODE_MULTI ) ) svgJob->m_genMode = JOB_EXPORT_PCB_SVG::GEN_MODE::MULTI; else if( m_argParser.get<bool>( ARG_MODE_SINGLE ) ) @@ -205,7 +190,5 @@ int CLI::PCB_EXPORT_SVG_COMMAND::doPerform( KIWAY& aKiway ) _( "The new behavior will match --mode-multi" ) ); } - int exitCode = aKiway.ProcessJob( KIWAY::FACE_PCB, svgJob.get() ); - - return exitCode; + return aKiway.ProcessJob( KIWAY::FACE_PCB, svgJob.get() ); } diff --git a/pcbnew/pcbnew_jobs_handler.cpp b/pcbnew/pcbnew_jobs_handler.cpp index 10eebe69fa..8dc4ac927b 100644 --- a/pcbnew/pcbnew_jobs_handler.cpp +++ b/pcbnew/pcbnew_jobs_handler.cpp @@ -330,6 +330,75 @@ BOARD* PCBNEW_JOBS_HANDLER::getBoard( const wxString& aPath ) } +LSEQ PCBNEW_JOBS_HANDLER::convertLayerArg( wxString& aLayerString, BOARD* aBoard ) const +{ + std::map<wxString, LSET> layerMasks; + std::map<wxString, LSET> layerGuiMasks; + + // Build list of layer names and their layer mask: + for( PCB_LAYER_ID layer : LSET::AllLayersMask().Seq() ) + { + // Add layer name used in pcb files + layerMasks[ LSET::Name( layer ) ] = LSET( { layer } ); + // Add layer name using GUI canonical layer name + layerGuiMasks[ LayerName( layer ) ] = LSET( { layer } ); + + // Add user layer name + if( aBoard ) + layerGuiMasks[ aBoard->GetLayerName( layer ) ] = LSET( { layer } ); + } + + // Add list of grouped layer names used in pcb files + layerMasks[ wxT( "*" ) ] = LSET::AllLayersMask(); + layerMasks[ wxT( "*.Cu" ) ] = LSET::AllCuMask(); + layerMasks[ wxT( "*In.Cu" ) ] = LSET::InternalCuMask(); + layerMasks[ wxT( "F&B.Cu" ) ] = LSET( { F_Cu, B_Cu } ); + layerMasks[ wxT( "*.Adhes" ) ] = LSET( { B_Adhes, F_Adhes } ); + layerMasks[ wxT( "*.Paste" ) ] = LSET( { B_Paste, F_Paste } ); + layerMasks[ wxT( "*.Mask" ) ] = LSET( { B_Mask, F_Mask } ); + layerMasks[ wxT( "*.SilkS" ) ] = LSET( { B_SilkS, F_SilkS } ); + layerMasks[ wxT( "*.Fab" ) ] = LSET( { B_Fab, F_Fab } ); + layerMasks[ wxT( "*.CrtYd" ) ] = LSET( { B_CrtYd, F_CrtYd } ); + + // Add list of grouped layer names using GUI canonical layer names + layerGuiMasks[ wxT( "*.Adhesive" ) ] = LSET( { B_Adhes, F_Adhes } ); + layerGuiMasks[ wxT( "*.Silkscreen" ) ] = LSET( { B_SilkS, F_SilkS } ); + layerGuiMasks[ wxT( "*.Courtyard" ) ] = LSET( { B_CrtYd, F_CrtYd } ); + + LSEQ layerMask; + + if( !aLayerString.IsEmpty() ) + { + wxStringTokenizer layerTokens( aLayerString, "," ); + + while( layerTokens.HasMoreTokens() ) + { + std::string token = TO_UTF8( layerTokens.GetNextToken() ); + + // Search for a layer name in canonical layer name used in .kicad_pcb files: + if( layerMasks.count( token ) ) + { + for( PCB_LAYER_ID layer : layerMasks.at( token ).Seq() ) + layerMask.push_back( layer ); + } + // Search for a layer name in canonical layer name used in GUI (not translated): + else if( layerGuiMasks.count( token ) ) + { + for( PCB_LAYER_ID layer : layerGuiMasks.at( token ).Seq() ) + layerMask.push_back( layer ); + } + else + { + m_reporter->Report( wxString::Format( _( "Invalid layer name \"%s\"\n" ), + token ) ); + } + } + } + + return layerMask; +} + + int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob ) { JOB_EXPORT_PCB_3D* aStepJob = dynamic_cast<JOB_EXPORT_PCB_3D*>( aJob ); @@ -753,6 +822,14 @@ int PCBNEW_JOBS_HANDLER::JobExportSvg( JOB* aJob ) loadOverrideDrawingSheet( brd, aSvgJob->m_drawingSheet ); brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() ); brd->SynchronizeProperties(); + aSvgJob->m_plotLayerSequence = convertLayerArg( aSvgJob->m_argLayers, brd ); + aSvgJob->m_plotOnAllLayersSequence = convertLayerArg( aSvgJob->m_argCommonLayers, brd ); + + if( aSvgJob->m_plotLayerSequence.size() < 1 ) + { + m_reporter->Report( _( "At least one layer must be specified\n" ), RPT_SEVERITY_ERROR ); + return CLI::EXIT_CODES::ERR_ARGS; + } PCB_PLOT_PARAMS plotOpts; PCB_PLOTTER::PlotJobToPlotOpts( plotOpts, aSvgJob, *m_reporter ); @@ -802,7 +879,14 @@ int PCBNEW_JOBS_HANDLER::JobExportDxf( JOB* aJob ) loadOverrideDrawingSheet( brd, aDxfJob->m_drawingSheet ); brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() ); brd->SynchronizeProperties(); + aDxfJob->m_plotLayerSequence = convertLayerArg( aDxfJob->m_argLayers, brd ); + aDxfJob->m_plotOnAllLayersSequence = convertLayerArg( aDxfJob->m_argCommonLayers, brd ); + if( aDxfJob->m_plotLayerSequence.size() < 1 ) + { + m_reporter->Report( _( "At least one layer must be specified\n" ), RPT_SEVERITY_ERROR ); + return CLI::EXIT_CODES::ERR_ARGS; + } if( aDxfJob->m_genMode == JOB_EXPORT_PCB_DXF::GEN_MODE::SINGLE ) { @@ -872,6 +956,14 @@ int PCBNEW_JOBS_HANDLER::JobExportPdf( JOB* aJob ) loadOverrideDrawingSheet( brd, aPdfJob->m_drawingSheet ); brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() ); brd->SynchronizeProperties(); + aPdfJob->m_plotLayerSequence = convertLayerArg( aPdfJob->m_argLayers, brd ); + aPdfJob->m_plotOnAllLayersSequence = convertLayerArg( aPdfJob->m_argCommonLayers, brd ); + + if( aPdfJob->m_plotLayerSequence.size() < 1 ) + { + m_reporter->Report( _( "At least one layer must be specified\n" ), RPT_SEVERITY_ERROR ); + return CLI::EXIT_CODES::ERR_ARGS; + } if( aPdfJob->m_pdfGenMode == JOB_EXPORT_PCB_PDF::GEN_MODE::ALL_LAYERS_ONE_FILE && aPdfJob->GetConfiguredOutputPath().IsEmpty() ) @@ -960,6 +1052,13 @@ int PCBNEW_JOBS_HANDLER::JobExportGerbers( JOB* aJob ) brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() ); brd->SynchronizeProperties(); + if( !aGerberJob->m_argLayers.empty() ) + aGerberJob->m_plotLayerSequence = convertLayerArg( aGerberJob->m_argLayers, nullptr ); + else + aGerberJob->m_plotLayerSequence = LSET::AllLayersMask().SeqStackupForPlotting(); + + aGerberJob->m_plotOnAllLayersSequence = convertLayerArg( aGerberJob->m_argCommonLayers, brd ); + PCB_PLOT_PARAMS boardPlotOptions = brd->GetPlotOptions(); GERBER_JOBFILE_WRITER jobfile_writer( brd ); @@ -1177,6 +1276,14 @@ int PCBNEW_JOBS_HANDLER::JobExportGerber( JOB* aJob ) aJob->SetTitleBlock( brd->GetTitleBlock() ); brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() ); brd->SynchronizeProperties(); + aGerberJob->m_plotLayerSequence = convertLayerArg( aGerberJob->m_argLayers, brd ); + aGerberJob->m_plotOnAllLayersSequence = convertLayerArg( aGerberJob->m_argCommonLayers, brd ); + + if( aGerberJob->m_plotLayerSequence.size() < 1 ) + { + m_reporter->Report( _( "At least one layer must be specified\n" ), RPT_SEVERITY_ERROR ); + return CLI::EXIT_CODES::ERR_ARGS; + } if( aGerberJob->GetConfiguredOutputPath().IsEmpty() ) { @@ -1654,6 +1761,11 @@ int PCBNEW_JOBS_HANDLER::JobExportFpSvg( JOB* aJob ) PCB_IO_KICAD_SEXPR pcb_io( CTL_FOR_LIBRARY ); FP_CACHE fpLib( &pcb_io, svgJob->m_libraryPath ); + if( !svgJob->m_argLayers.empty() ) + svgJob->m_plotLayerSequence = convertLayerArg( svgJob->m_argLayers, nullptr ); + else + svgJob->m_plotLayerSequence = LSET::AllLayersMask().SeqStackupForPlotting(); + try { fpLib.Load(); diff --git a/pcbnew/pcbnew_jobs_handler.h b/pcbnew/pcbnew_jobs_handler.h index db9957a8aa..a54f3f7e6f 100644 --- a/pcbnew/pcbnew_jobs_handler.h +++ b/pcbnew/pcbnew_jobs_handler.h @@ -55,6 +55,8 @@ public: private: BOARD* getBoard( const wxString& aPath = wxEmptyString ); + LSEQ convertLayerArg( wxString& aLayerString, BOARD* aBoard ) const; + void populateGerberPlotOptionsFromJob( PCB_PLOT_PARAMS& aPlotOpts, JOB_EXPORT_PCB_GERBER* aJob ); void populateGerberPlotOptionsFromJob( PCB_PLOT_PARAMS& aPlotOpts,