From 5c3004b96e46fc3bcd50bbd1f7e71e0194c046c1 Mon Sep 17 00:00:00 2001
From: Marek Roszko <mark.roszko@gmail.com>
Date: Tue, 14 Jan 2025 20:02:53 -0500
Subject: [PATCH] Avoid altering the configured output path during run in case
 of empty paths

---
 common/dialogs/dialog_rc_job.cpp              |  4 +-
 common/jobs/job.cpp                           |  9 ++--
 common/jobs/job.h                             | 37 ++++++++++++++--
 common/jobs/job_export_pcb_ipc2581.cpp        |  2 +-
 common/jobs/job_export_pcb_odb.cpp            |  2 +-
 common/jobs/job_export_pcb_pos.cpp            |  2 +-
 eeschema/dialogs/dialog_export_netlist.cpp    |  4 +-
 eeschema/dialogs/dialog_plot_schematic.cpp    |  4 +-
 .../dialogs/dialog_symbol_fields_table.cpp    |  4 +-
 eeschema/eeschema_jobs_handler.cpp            | 20 ++++-----
 kicad/cli/command_pcb_drc.cpp                 |  2 +-
 kicad/cli/command_pcb_export_3d.cpp           |  2 +-
 kicad/cli/command_pcb_export_drill.cpp        |  6 +--
 kicad/cli/command_pcb_export_dxf.cpp          |  2 +-
 kicad/cli/command_pcb_export_gerber.cpp       |  2 +-
 kicad/cli/command_pcb_export_ipc2581.cpp      |  2 +-
 kicad/cli/command_pcb_export_odb.cpp          |  2 +-
 kicad/cli/command_pcb_export_pdf.cpp          |  2 +-
 kicad/cli/command_pcb_export_pos.cpp          |  2 +-
 kicad/cli/command_pcb_export_svg.cpp          |  2 +-
 kicad/cli/command_pcb_render.cpp              |  2 +-
 kicad/cli/command_sch_erc.cpp                 |  2 +-
 kicad/cli/command_sch_export_bom.cpp          |  2 +-
 kicad/cli/command_sch_export_netlist.cpp      |  2 +-
 kicad/cli/command_sch_export_plot.cpp         |  2 +-
 kicad/cli/command_sch_export_pythonbom.cpp    |  2 +-
 .../dialog_executecommand_job_settings.cpp    |  4 +-
 kicad/jobs_runner.cpp                         |  4 +-
 pcbnew/dialogs/dialog_export_2581.cpp         |  4 +-
 pcbnew/dialogs/dialog_export_odbpp.cpp        |  6 +--
 pcbnew/dialogs/dialog_export_step.cpp         |  4 +-
 .../dialogs/dialog_gen_footprint_position.cpp |  4 +-
 pcbnew/dialogs/dialog_gendrill.cpp            |  4 +-
 pcbnew/dialogs/dialog_plot.cpp                |  2 +-
 pcbnew/dialogs/dialog_render_job.cpp          |  4 +-
 pcbnew/files.cpp                              |  2 +-
 pcbnew/pcb_plotter.cpp                        |  2 +-
 pcbnew/pcbnew_jobs_handler.cpp                | 44 +++++++++----------
 38 files changed, 121 insertions(+), 87 deletions(-)

diff --git a/common/dialogs/dialog_rc_job.cpp b/common/dialogs/dialog_rc_job.cpp
index 8c5de5ab68..2c014f8ef7 100644
--- a/common/dialogs/dialog_rc_job.cpp
+++ b/common/dialogs/dialog_rc_job.cpp
@@ -81,7 +81,7 @@ void DIALOG_RC_JOB::OnFormatChoice( wxCommandEvent& event )
 
 bool DIALOG_RC_JOB::TransferDataToWindow()
 {
-    m_textCtrlOutputPath->SetValue( m_job->GetOutputPath() );
+    m_textCtrlOutputPath->SetValue( m_job->GetConfiguredOutputPath() );
     setSelectedFormat( m_job->m_format );
     m_cbHaltOutput->SetValue( m_job->m_exitCodeViolations );
 
@@ -94,7 +94,7 @@ bool DIALOG_RC_JOB::TransferDataToWindow()
 
 bool DIALOG_RC_JOB::TransferDataFromWindow()
 {
-    m_job->SetOutputPath( m_textCtrlOutputPath->GetValue() );
+    m_job->SetConfiguredOutputPath( m_textCtrlOutputPath->GetValue() );
     m_job->m_format = getSelectedFormat();
     m_job->m_exitCodeViolations = m_cbHaltOutput->GetValue();
 
diff --git a/common/jobs/job.cpp b/common/jobs/job.cpp
index 951e444b9d..30eb4fd4ec 100644
--- a/common/jobs/job.cpp
+++ b/common/jobs/job.cpp
@@ -28,7 +28,8 @@ JOB::JOB( const std::string& aType, bool aOutputIsDirectory ) :
         m_tempOutputDirectory(),
         m_outputPath(),
         m_outputPathIsDirectory( aOutputIsDirectory ),
-        m_description()
+        m_description(),
+        m_workingOutputPath()
 {
     m_params.emplace_back( new JOB_PARAM<wxString>( "description",
                                                     &m_description, m_description ) );
@@ -103,7 +104,9 @@ wxString JOB::GetFullOutputPath( PROJECT* aProject ) const
                 return m_titleBlock.TextVarResolver( token, aProject );
             };
 
-    wxString outPath = ExpandTextVars( m_outputPath, &textResolver );
+    // use the working output path (nonsaved) over the configured path if its not empty
+    wxString outPath = m_workingOutputPath.IsEmpty() ? m_outputPath : m_workingOutputPath;
+    outPath = ExpandTextVars( outPath, &textResolver );
 
     if( !m_tempOutputDirectory.IsEmpty() )
     {
@@ -140,7 +143,7 @@ wxString JOB::GetFullOutputPath( PROJECT* aProject ) const
 }
 
 
-void JOB::SetOutputPath( const wxString& aPath )
+void JOB::SetConfiguredOutputPath( const wxString& aPath )
 {
     m_outputPath = aPath;
 }
diff --git a/common/jobs/job.h b/common/jobs/job.h
index c617f8cb93..364a0621e6 100644
--- a/common/jobs/job.h
+++ b/common/jobs/job.h
@@ -208,15 +208,45 @@ public:
     const std::vector<JOB_OUTPUT>& GetOutputs() { return m_outputs; }
     void AddOutput( wxString aOutputPath )      { m_outputs.emplace_back( aOutputPath ); }
 
+    /**
+     * Sets the temporary output directory for the job, this is used to prefix with a given
+     * output path when GetFullOutputPath is called. This is intended for use with running jobsets
+     * and otherwise has no impact on individual job runs outside jobsets.
+     */
     void SetTempOutputDirectory( const wxString& aBase );
 
-    void SetOutputPath( const wxString& aPath );
-    wxString GetOutputPath() const { return m_outputPath; }
+    /**
+     * Sets the configured output path for the job, this path is always saved to file
+     */
+    void SetConfiguredOutputPath( const wxString& aPath );
+
+    /**
+     * Returns the configured output path for the job
+     */
+    wxString GetConfiguredOutputPath() const { return m_outputPath; }
+
+    /**
+     * Sets a transient output path for the job, it takes priority over the configured output path
+     * when GetFullOutputPath is called.
+     */
+    void     SetWorkingOutputPath( const wxString& aPath ) { m_workingOutputPath = aPath; }
+
+    /**
+     * Returns the working output path for the job, if one has been set
+     */
+    wxString GetWorkingOutputPath() const { return m_workingOutputPath; }
+
+    /**
+     * Returns the full output path for the job, taking into account the configured output path,
+     * any configured working path and the temporary output directory.
+     *
+     * Additionally variable resolution will take place
+     */
     wxString GetFullOutputPath( PROJECT* aProject ) const;
 
     bool OutputPathFullSpecified() const;
 
-    bool GetOutpathIsDirectory() const { return m_outputPathIsDirectory; }
+    bool GetOutputPathIsDirectory() const { return m_outputPathIsDirectory; }
 
 protected:
     std::string                  m_type;
@@ -228,6 +258,7 @@ protected:
     wxString m_outputPath;
     bool     m_outputPathIsDirectory;
     wxString m_description;
+    wxString m_workingOutputPath;
 
     std::vector<JOB_PARAM_BASE*> m_params;
 
diff --git a/common/jobs/job_export_pcb_ipc2581.cpp b/common/jobs/job_export_pcb_ipc2581.cpp
index 27bc0ecc11..684219bd84 100644
--- a/common/jobs/job_export_pcb_ipc2581.cpp
+++ b/common/jobs/job_export_pcb_ipc2581.cpp
@@ -85,7 +85,7 @@ void JOB_EXPORT_PCB_IPC2581::SetDefaultOutputPath( const wxString& aReferenceNam
 
     fn.SetExt( FILEEXT::Ipc2581FileExtension );
 
-    SetOutputPath( fn.GetFullName() );
+    SetConfiguredOutputPath( fn.GetFullName() );
 }
 
 REGISTER_JOB( pcb_export_ipc2581, _HKI( "PCB: Export IPC2581" ), KIWAY::FACE_PCB,
diff --git a/common/jobs/job_export_pcb_odb.cpp b/common/jobs/job_export_pcb_odb.cpp
index dd366c4d08..3772c31023 100644
--- a/common/jobs/job_export_pcb_odb.cpp
+++ b/common/jobs/job_export_pcb_odb.cpp
@@ -70,7 +70,7 @@ void JOB_EXPORT_PCB_ODB::SetDefaultOutputPath( const wxString& aReferenceName )
 
     fn.SetExt( "zip" );
 
-    SetOutputPath( fn.GetFullName() );
+    SetConfiguredOutputPath( fn.GetFullName() );
 }
 
 REGISTER_JOB( pcb_export_odb, _HKI( "PCB: Export ODB++" ), KIWAY::FACE_PCB,
diff --git a/common/jobs/job_export_pcb_pos.cpp b/common/jobs/job_export_pcb_pos.cpp
index e4ce0cafa4..cef2e028c4 100644
--- a/common/jobs/job_export_pcb_pos.cpp
+++ b/common/jobs/job_export_pcb_pos.cpp
@@ -109,7 +109,7 @@ void JOB_EXPORT_PCB_POS::SetDefaultOutputPath( const wxString& aReferenceName )
     else if( m_format == JOB_EXPORT_PCB_POS::FORMAT::GERBER )
         fn.SetExt( FILEEXT::GerberFileExtension );
 
-    SetOutputPath( fn.GetFullName() );
+    SetConfiguredOutputPath( fn.GetFullName() );
 }
 
 REGISTER_JOB( pcb_export_pos, _HKI( "PCB: Export Position Data" ), KIWAY::FACE_PCB, JOB_EXPORT_PCB_POS );
\ No newline at end of file
diff --git a/eeschema/dialogs/dialog_export_netlist.cpp b/eeschema/dialogs/dialog_export_netlist.cpp
index 0fd8f30299..ec3039945b 100644
--- a/eeschema/dialogs/dialog_export_netlist.cpp
+++ b/eeschema/dialogs/dialog_export_netlist.cpp
@@ -263,7 +263,7 @@ DIALOG_EXPORT_NETLIST::DIALOG_EXPORT_NETLIST( SCH_EDIT_FRAME* aEditFrame, wxWind
         SetTitle( m_job->GetSettingsDialogTitle() );
 
         m_MessagesBox->Hide();
-        m_outputPath->SetValue( m_job->GetOutputPath() );
+        m_outputPath->SetValue( m_job->GetConfiguredOutputPath() );
 
         SetupStandardButtons();
 
@@ -473,7 +473,7 @@ bool DIALOG_EXPORT_NETLIST::NetlistUpdateOpt()
             }
         }
 
-        m_job->SetOutputPath( m_outputPath->GetValue() );
+        m_job->SetConfiguredOutputPath( m_outputPath->GetValue() );
         m_job->m_spiceSaveAllVoltages = saveAllVoltages;
         m_job->m_spiceSaveAllCurrents = saveAllCurrents;
         m_job->m_spiceSaveAllDissipations = saveAllDissipations;
diff --git a/eeschema/dialogs/dialog_plot_schematic.cpp b/eeschema/dialogs/dialog_plot_schematic.cpp
index 77311321bb..561a3540cc 100644
--- a/eeschema/dialogs/dialog_plot_schematic.cpp
+++ b/eeschema/dialogs/dialog_plot_schematic.cpp
@@ -226,7 +226,7 @@ void DIALOG_PLOT_SCHEMATIC::initDlg()
         // And then hide it
         m_plotFormatOpt->Hide();
 
-        m_outputDirectoryName->SetValue( m_job->GetOutputPath() );
+        m_outputDirectoryName->SetValue( m_job->GetConfiguredOutputPath() );
     }
 }
 
@@ -455,7 +455,7 @@ void DIALOG_PLOT_SCHEMATIC::OnPlotAll( wxCommandEvent& event )
         m_job->m_PDFMetadata = m_plotPDFMetadata->GetValue();
         m_job->m_plotDrawingSheet = m_plotDrawingSheet->GetValue();
         m_job->m_plotAll = true;
-        m_job->SetOutputPath( m_outputDirectoryName->GetValue() );
+        m_job->SetConfiguredOutputPath( m_outputDirectoryName->GetValue() );
 
         m_job->m_HPGLPlotOrigin =
                 static_cast<JOB_HPGL_PLOT_ORIGIN_AND_UNITS>( m_plotOriginOpt->GetSelection() );
diff --git a/eeschema/dialogs/dialog_symbol_fields_table.cpp b/eeschema/dialogs/dialog_symbol_fields_table.cpp
index 2d3684d208..1c27b93d51 100644
--- a/eeschema/dialogs/dialog_symbol_fields_table.cpp
+++ b/eeschema/dialogs/dialog_symbol_fields_table.cpp
@@ -367,7 +367,7 @@ DIALOG_SYMBOL_FIELDS_TABLE::DIALOG_SYMBOL_FIELDS_TABLE( SCH_EDIT_FRAME* parent,
 
     if( m_job )
     {
-        m_outputFileName->SetValue( m_job->GetOutputPath() );
+        m_outputFileName->SetValue( m_job->GetConfiguredOutputPath() );
     }
     else
     {
@@ -1422,7 +1422,7 @@ void DIALOG_SYMBOL_FIELDS_TABLE::OnOk( wxCommandEvent& aEvent )
 
     if( m_job )
     {
-        m_job->SetOutputPath( m_outputFileName->GetValue() );
+        m_job->SetConfiguredOutputPath( m_outputFileName->GetValue() );
 
         if( m_currentBomFmtPreset )
             m_job->m_bomFmtPresetName = m_currentBomFmtPreset->name;
diff --git a/eeschema/eeschema_jobs_handler.cpp b/eeschema/eeschema_jobs_handler.cpp
index 6d1aa5f1a9..4401996f24 100644
--- a/eeschema/eeschema_jobs_handler.cpp
+++ b/eeschema/eeschema_jobs_handler.cpp
@@ -337,7 +337,7 @@ int EESCHEMA_JOBS_HANDLER::JobExportPlot( JOB* aJob )
 
     wxString outPath = aPlotJob->GetFullOutputPath( &sch->Prj() );
     if( !PATHS::EnsurePathExists( outPath,
-                                  !aPlotJob->GetOutpathIsDirectory() ) )
+                                  !aPlotJob->GetOutputPathIsDirectory() ) )
     {
         m_reporter->Report( _( "Failed to create output directory\n" ), RPT_SEVERITY_ERROR );
         return CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
@@ -351,7 +351,7 @@ int EESCHEMA_JOBS_HANDLER::JobExportPlot( JOB* aJob )
     plotOpts.m_PDFPropertyPopups = aPlotJob->m_PDFPropertyPopups;
     plotOpts.m_PDFHierarchicalLinks = aPlotJob->m_PDFHierarchicalLinks;
     plotOpts.m_PDFMetadata = aPlotJob->m_PDFMetadata;
-    if( aPlotJob->GetOutpathIsDirectory() )
+    if( aPlotJob->GetOutputPathIsDirectory() )
     {
         plotOpts.m_outputDirectory = outPath;
         plotOpts.m_outputFile = wxEmptyString;
@@ -467,13 +467,13 @@ int EESCHEMA_JOBS_HANDLER::JobExportNetlist( JOB* aJob )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
     }
 
-    if( aNetJob->GetOutputPath().IsEmpty() )
+    if( aNetJob->GetConfiguredOutputPath().IsEmpty() )
     {
         wxFileName fn = sch->GetFileName();
         fn.SetName( fn.GetName() );
         fn.SetExt( fileExt );
 
-        aNetJob->SetOutputPath( fn.GetFullName() );
+        aNetJob->SetConfiguredOutputPath( fn.GetFullName() );
     }
 
     wxString outPath = aNetJob->GetFullOutputPath( &sch->Prj() );
@@ -678,13 +678,13 @@ int EESCHEMA_JOBS_HANDLER::JobExportBom( JOB* aJob )
 
     dataModel.ApplyBomPreset( preset );
 
-    if( aBomJob->GetOutputPath().IsEmpty() )
+    if( aBomJob->GetConfiguredOutputPath().IsEmpty() )
     {
         wxFileName fn = sch->GetFileName();
         fn.SetName( fn.GetName() );
         fn.SetExt( FILEEXT::CsvFileExtension );
 
-        aBomJob->SetOutputPath( fn.GetFullName() );
+        aBomJob->SetConfiguredOutputPath( fn.GetFullName() );
     }
 
     wxString outPath = aBomJob->GetFullOutputPath( &sch->Prj() );
@@ -801,13 +801,13 @@ int EESCHEMA_JOBS_HANDLER::JobExportPythonBom( JOB* aJob )
     std::unique_ptr<NETLIST_EXPORTER_XML> xmlNetlist =
             std::make_unique<NETLIST_EXPORTER_XML>( sch );
 
-    if( aNetJob->GetOutputPath().IsEmpty() )
+    if( aNetJob->GetConfiguredOutputPath().IsEmpty() )
     {
         wxFileName fn = sch->GetFileName();
         fn.SetName( fn.GetName() + "-bom" );
         fn.SetExt( FILEEXT::XmlFileExtension );
 
-        aNetJob->SetOutputPath( fn.GetFullName() );
+        aNetJob->SetConfiguredOutputPath( fn.GetFullName() );
     }
 
     wxString outPath = aNetJob->GetFullOutputPath( &sch->Prj() );
@@ -1116,7 +1116,7 @@ int EESCHEMA_JOBS_HANDLER::JobSchErc( JOB* aJob )
     aJob->SetTitleBlock( sch->RootScreen()->GetTitleBlock() );
     sch->Prj().ApplyTextVars( aJob->GetVarOverrides() );
 
-    if( ercJob->GetOutputPath().IsEmpty() )
+    if( ercJob->GetConfiguredOutputPath().IsEmpty() )
     {
         wxFileName fn = sch->GetFileName();
         fn.SetName( fn.GetName() + wxS( "-erc" ) );
@@ -1126,7 +1126,7 @@ int EESCHEMA_JOBS_HANDLER::JobSchErc( JOB* aJob )
         else
             fn.SetExt( FILEEXT::ReportFileExtension );
 
-        ercJob->SetOutputPath( fn.GetFullName() );
+        ercJob->SetConfiguredOutputPath( fn.GetFullName() );
     }
 
     wxString outPath = ercJob->GetFullOutputPath( &sch->Prj() );
diff --git a/kicad/cli/command_pcb_drc.cpp b/kicad/cli/command_pcb_drc.cpp
index 1e2b6ed985..1f6ac07fbf 100644
--- a/kicad/cli/command_pcb_drc.cpp
+++ b/kicad/cli/command_pcb_drc.cpp
@@ -95,7 +95,7 @@ int CLI::PCB_DRC_COMMAND::doPerform( KIWAY& aKiway )
 {
     std::unique_ptr<JOB_PCB_DRC> drcJob( new JOB_PCB_DRC() );
 
-    drcJob->SetOutputPath( m_argOutput );
+    drcJob->SetConfiguredOutputPath( m_argOutput );
     drcJob->m_filename = m_argInput;
     drcJob->SetVarOverrides( m_argDefineVars );
     drcJob->m_reportAllTrackErrors = m_argParser.get<bool>( ARG_ALL_TRACK_ERRORS );
diff --git a/kicad/cli/command_pcb_export_3d.cpp b/kicad/cli/command_pcb_export_3d.cpp
index e81aca2206..f59f4fb655 100644
--- a/kicad/cli/command_pcb_export_3d.cpp
+++ b/kicad/cli/command_pcb_export_3d.cpp
@@ -247,7 +247,7 @@ int CLI::PCB_EXPORT_3D_COMMAND::doPerform( KIWAY& aKiway )
     params.m_IncludeUnspecified = !m_argParser.get<bool>( ARG_NO_UNSPECIFIED );
     params.m_IncludeDNP = !m_argParser.get<bool>( ARG_NO_DNP );
     params.m_Overwrite = m_argParser.get<bool>( ARG_FORCE );
-    step->SetOutputPath( m_argOutput );
+    step->SetConfiguredOutputPath( m_argOutput );
 
     step->m_filename = m_argInput;
     step->m_format = m_format;
diff --git a/kicad/cli/command_pcb_export_drill.cpp b/kicad/cli/command_pcb_export_drill.cpp
index 48b8f5d8fc..3ac215621b 100644
--- a/kicad/cli/command_pcb_export_drill.cpp
+++ b/kicad/cli/command_pcb_export_drill.cpp
@@ -106,11 +106,11 @@ int CLI::PCB_EXPORT_DRILL_COMMAND::doPerform( KIWAY& aKiway )
     std::unique_ptr<JOB_EXPORT_PCB_DRILL> drillJob( new JOB_EXPORT_PCB_DRILL() );
 
     drillJob->m_filename = m_argInput;
-    drillJob->SetOutputPath( m_argOutput );
+    drillJob->SetConfiguredOutputPath( m_argOutput );
 
-    if( !drillJob->GetOutputPath().IsEmpty() )
+    if( !drillJob->GetConfiguredOutputPath().IsEmpty() )
     {
-        wxFileName fn( drillJob->GetOutputPath(), wxEmptyString );
+        wxFileName fn( drillJob->GetConfiguredOutputPath(), wxEmptyString );
 
         if( !fn.IsDir() )
         {
diff --git a/kicad/cli/command_pcb_export_dxf.cpp b/kicad/cli/command_pcb_export_dxf.cpp
index 8e3fafb85f..4f97ff94e5 100644
--- a/kicad/cli/command_pcb_export_dxf.cpp
+++ b/kicad/cli/command_pcb_export_dxf.cpp
@@ -111,7 +111,7 @@ int CLI::PCB_EXPORT_DXF_COMMAND::doPerform( KIWAY& aKiway )
     std::unique_ptr<JOB_EXPORT_PCB_DXF> dxfJob( new JOB_EXPORT_PCB_DXF() );
 
     dxfJob->m_filename = m_argInput;
-    dxfJob->SetOutputPath( m_argOutput );
+    dxfJob->SetConfiguredOutputPath( m_argOutput );
     dxfJob->m_drawingSheet = m_argDrawingSheet;
     dxfJob->SetVarOverrides( m_argDefineVars );
 
diff --git a/kicad/cli/command_pcb_export_gerber.cpp b/kicad/cli/command_pcb_export_gerber.cpp
index d96b9c4942..1df26fc167 100644
--- a/kicad/cli/command_pcb_export_gerber.cpp
+++ b/kicad/cli/command_pcb_export_gerber.cpp
@@ -99,7 +99,7 @@ CLI::PCB_EXPORT_GERBER_COMMAND::PCB_EXPORT_GERBER_COMMAND() : PCB_EXPORT_GERBER_
 int CLI::PCB_EXPORT_GERBER_COMMAND::populateJob( JOB_EXPORT_PCB_GERBER* aJob )
 {
     aJob->m_filename = m_argInput;
-    aJob->SetOutputPath( m_argOutput );
+    aJob->SetConfiguredOutputPath( m_argOutput );
     aJob->m_drawingSheet = m_argDrawingSheet;
     aJob->SetVarOverrides( m_argDefineVars );
 
diff --git a/kicad/cli/command_pcb_export_ipc2581.cpp b/kicad/cli/command_pcb_export_ipc2581.cpp
index b2c84974bc..b7d9d42065 100644
--- a/kicad/cli/command_pcb_export_ipc2581.cpp
+++ b/kicad/cli/command_pcb_export_ipc2581.cpp
@@ -110,7 +110,7 @@ int CLI::PCB_EXPORT_IPC2581_COMMAND::doPerform( KIWAY& aKiway )
     std::unique_ptr<JOB_EXPORT_PCB_IPC2581> ipc2581Job( new JOB_EXPORT_PCB_IPC2581() );
 
     ipc2581Job->m_filename = m_argInput;
-    ipc2581Job->SetOutputPath( m_argOutput );
+    ipc2581Job->SetConfiguredOutputPath( m_argOutput );
     ipc2581Job->m_drawingSheet = m_argDrawingSheet;
     ipc2581Job->SetVarOverrides( m_argDefineVars );
 
diff --git a/kicad/cli/command_pcb_export_odb.cpp b/kicad/cli/command_pcb_export_odb.cpp
index ec6144403d..8944145126 100644
--- a/kicad/cli/command_pcb_export_odb.cpp
+++ b/kicad/cli/command_pcb_export_odb.cpp
@@ -68,7 +68,7 @@ int CLI::PCB_EXPORT_ODB_COMMAND::doPerform( KIWAY& aKiway )
     std::unique_ptr<JOB_EXPORT_PCB_ODB> job( new JOB_EXPORT_PCB_ODB() );
 
     job->m_filename = m_argInput;
-    job->SetOutputPath( m_argOutput );
+    job->SetConfiguredOutputPath( m_argOutput );
     job->m_drawingSheet = m_argDrawingSheet;
     job->SetVarOverrides( m_argDefineVars );
 
diff --git a/kicad/cli/command_pcb_export_pdf.cpp b/kicad/cli/command_pcb_export_pdf.cpp
index 4e622dc9ab..475ed327d7 100644
--- a/kicad/cli/command_pcb_export_pdf.cpp
+++ b/kicad/cli/command_pcb_export_pdf.cpp
@@ -129,7 +129,7 @@ int CLI::PCB_EXPORT_PDF_COMMAND::doPerform( KIWAY& aKiway )
     std::unique_ptr<JOB_EXPORT_PCB_PDF> pdfJob( new JOB_EXPORT_PCB_PDF() );
 
     pdfJob->m_filename = m_argInput;
-    pdfJob->SetOutputPath( m_argOutput );
+    pdfJob->SetConfiguredOutputPath( m_argOutput );
     pdfJob->m_drawingSheet = m_argDrawingSheet;
     pdfJob->SetVarOverrides( m_argDefineVars );
 
diff --git a/kicad/cli/command_pcb_export_pos.cpp b/kicad/cli/command_pcb_export_pos.cpp
index 28f4ff5e90..5b665ee583 100644
--- a/kicad/cli/command_pcb_export_pos.cpp
+++ b/kicad/cli/command_pcb_export_pos.cpp
@@ -99,7 +99,7 @@ int CLI::PCB_EXPORT_POS_COMMAND::doPerform( KIWAY& aKiway )
     std::unique_ptr<JOB_EXPORT_PCB_POS> aPosJob( new JOB_EXPORT_PCB_POS() );
 
     aPosJob->m_filename = m_argInput;
-    aPosJob->SetOutputPath( m_argOutput );
+    aPosJob->SetConfiguredOutputPath( m_argOutput );
 
     if( !wxFile::Exists( aPosJob->m_filename ) )
     {
diff --git a/kicad/cli/command_pcb_export_svg.cpp b/kicad/cli/command_pcb_export_svg.cpp
index a59b1918ba..01b4ef1061 100644
--- a/kicad/cli/command_pcb_export_svg.cpp
+++ b/kicad/cli/command_pcb_export_svg.cpp
@@ -144,7 +144,7 @@ int CLI::PCB_EXPORT_SVG_COMMAND::doPerform( KIWAY& aKiway )
     svgJob->m_plotInvisibleText = m_argParser.get<bool>( ARG_PLOT_INVISIBLE_TEXT );
 
     svgJob->m_filename = m_argInput;
-    svgJob->SetOutputPath( m_argOutput );
+    svgJob->SetConfiguredOutputPath( m_argOutput );
     svgJob->m_colorTheme = From_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
     svgJob->m_plotDrawingSheet = !m_argParser.get<bool>( ARG_EXCLUDE_DRAWING_SHEET );
     svgJob->SetVarOverrides( m_argDefineVars );
diff --git a/kicad/cli/command_pcb_render.cpp b/kicad/cli/command_pcb_render.cpp
index 0a01be1caf..5b868077c8 100644
--- a/kicad/cli/command_pcb_render.cpp
+++ b/kicad/cli/command_pcb_render.cpp
@@ -322,7 +322,7 @@ int CLI::PCB_RENDER_COMMAND::doPerform( KIWAY& aKiway )
 {
     std::unique_ptr<JOB_PCB_RENDER> renderJob( new JOB_PCB_RENDER() );
 
-    renderJob->SetOutputPath( m_argOutput );
+    renderJob->SetConfiguredOutputPath( m_argOutput );
     renderJob->m_filename = m_argInput;
     renderJob->SetVarOverrides( m_argDefineVars );
 
diff --git a/kicad/cli/command_sch_erc.cpp b/kicad/cli/command_sch_erc.cpp
index 20476241a3..a972d1a72f 100644
--- a/kicad/cli/command_sch_erc.cpp
+++ b/kicad/cli/command_sch_erc.cpp
@@ -85,7 +85,7 @@ int CLI::SCH_ERC_COMMAND::doPerform( KIWAY& aKiway )
 {
     std::unique_ptr<JOB_SCH_ERC> ercJob( new JOB_SCH_ERC() );
 
-    ercJob->SetOutputPath( m_argOutput );
+    ercJob->SetConfiguredOutputPath( m_argOutput );
     ercJob->m_filename = m_argInput;
     ercJob->m_exitCodeViolations = m_argParser.get<bool>( ARG_EXIT_CODE_VIOLATIONS );
     ercJob->SetVarOverrides( m_argDefineVars );
diff --git a/kicad/cli/command_sch_export_bom.cpp b/kicad/cli/command_sch_export_bom.cpp
index 220a79d3e2..4469c8ef3e 100644
--- a/kicad/cli/command_sch_export_bom.cpp
+++ b/kicad/cli/command_sch_export_bom.cpp
@@ -138,7 +138,7 @@ int CLI::SCH_EXPORT_BOM_COMMAND::doPerform( KIWAY& aKiway )
 
     // Basic options
     bomJob->m_filename = m_argInput;
-    bomJob->SetOutputPath( m_argOutput );
+    bomJob->SetConfiguredOutputPath( m_argOutput );
 
     bomJob->m_bomPresetName = From_UTF8( m_argParser.get<std::string>( ARG_PRESET ).c_str() );
     bomJob->m_bomFmtPresetName =
diff --git a/kicad/cli/command_sch_export_netlist.cpp b/kicad/cli/command_sch_export_netlist.cpp
index 8d91a2f2b0..9b782156d8 100644
--- a/kicad/cli/command_sch_export_netlist.cpp
+++ b/kicad/cli/command_sch_export_netlist.cpp
@@ -49,7 +49,7 @@ int CLI::SCH_EXPORT_NETLIST_COMMAND::doPerform( KIWAY& aKiway )
             std::make_unique<JOB_EXPORT_SCH_NETLIST>();
 
     netJob->m_filename = m_argInput;
-    netJob->SetOutputPath( m_argOutput );
+    netJob->SetConfiguredOutputPath( m_argOutput );
 
     if( !wxFile::Exists( netJob->m_filename ) )
     {
diff --git a/kicad/cli/command_sch_export_plot.cpp b/kicad/cli/command_sch_export_plot.cpp
index ebebdb2b1e..7988abc2e8 100644
--- a/kicad/cli/command_sch_export_plot.cpp
+++ b/kicad/cli/command_sch_export_plot.cpp
@@ -180,7 +180,7 @@ int CLI::SCH_EXPORT_PLOT_COMMAND::doPerform( KIWAY& aKiway )
         plotJob->m_theme = From_UTF8( m_argParser.get<std::string>( ARG_THEME ).c_str() );
     }
 
-    plotJob->SetOutputPath( m_argOutput );
+    plotJob->SetConfiguredOutputPath( m_argOutput );
 
     plotJob->m_plotAll = plotJob->m_plotPages.size() == 0;
 
diff --git a/kicad/cli/command_sch_export_pythonbom.cpp b/kicad/cli/command_sch_export_pythonbom.cpp
index 661d30213d..b145da1a5f 100644
--- a/kicad/cli/command_sch_export_pythonbom.cpp
+++ b/kicad/cli/command_sch_export_pythonbom.cpp
@@ -44,7 +44,7 @@ int CLI::SCH_EXPORT_PYTHONBOM_COMMAND::doPerform( KIWAY& aKiway )
             std::make_unique<JOB_EXPORT_SCH_PYTHONBOM>();
 
     bomJob->m_filename = m_argInput;
-    bomJob->SetOutputPath( m_argOutput );
+    bomJob->SetConfiguredOutputPath( m_argOutput );
 
     if( !wxFile::Exists( bomJob->m_filename ) )
     {
diff --git a/kicad/dialogs/dialog_executecommand_job_settings.cpp b/kicad/dialogs/dialog_executecommand_job_settings.cpp
index dc93000115..087c112494 100644
--- a/kicad/dialogs/dialog_executecommand_job_settings.cpp
+++ b/kicad/dialogs/dialog_executecommand_job_settings.cpp
@@ -35,7 +35,7 @@ bool DIALOG_EXECUTECOMMAND_JOB_SETTINGS::TransferDataFromWindow()
     m_job->m_command = m_textCtrlCommand->GetValue();
     m_job->m_ignoreExitcode = m_cbIgnoreExitCode->GetValue();
     m_job->m_recordOutput = m_cbRecordOutput->GetValue();
-    m_job->SetOutputPath( m_textCtrlOutputPath->GetValue() );
+    m_job->SetConfiguredOutputPath( m_textCtrlOutputPath->GetValue() );
 
     return true;
 }
@@ -47,7 +47,7 @@ bool DIALOG_EXECUTECOMMAND_JOB_SETTINGS::TransferDataToWindow()
     m_cbIgnoreExitCode->SetValue( m_job->m_ignoreExitcode );
     m_cbRecordOutput->SetValue( m_job->m_recordOutput );
 
-    m_textCtrlOutputPath->SetValue( m_job->GetOutputPath() );
+    m_textCtrlOutputPath->SetValue( m_job->GetConfiguredOutputPath() );
     m_textCtrlOutputPath->Enable( m_cbRecordOutput->GetValue() );
 
     return true;
diff --git a/kicad/jobs_runner.cpp b/kicad/jobs_runner.cpp
index c4a7c531d2..673326af5c 100644
--- a/kicad/jobs_runner.cpp
+++ b/kicad/jobs_runner.cpp
@@ -75,11 +75,11 @@ int JOBS_RUNNER::runSpecialExecute( const JOBSET_JOB* aJob, PROJECT* aProject )
 
     if( specialJob->m_recordOutput )
     {
-        if( specialJob->GetOutputPath().IsEmpty() )
+        if( specialJob->GetConfiguredOutputPath().IsEmpty() )
         {
             wxFileName fn( aJob->m_id );
             fn.SetExt( wxT( "log" ) );
-            specialJob->SetOutputPath( fn.GetFullPath() );
+            specialJob->SetConfiguredOutputPath( fn.GetFullPath() );
         }
 
         wxFFileOutputStream procOutput( specialJob->GetFullOutputPath( aProject ) );
diff --git a/pcbnew/dialogs/dialog_export_2581.cpp b/pcbnew/dialogs/dialog_export_2581.cpp
index 66edf31df4..af6cd8d7d6 100644
--- a/pcbnew/dialogs/dialog_export_2581.cpp
+++ b/pcbnew/dialogs/dialog_export_2581.cpp
@@ -80,7 +80,7 @@ DIALOG_EXPORT_2581::DIALOG_EXPORT_2581( JOB_EXPORT_PCB_IPC2581* aJob, PCB_EDIT_F
 
     SetupStandardButtons();
 
-    m_outputFileName->SetValue( m_job->GetOutputPath() );
+    m_outputFileName->SetValue( m_job->GetConfiguredOutputPath() );
 
     m_textDistributor->SetSize( m_choiceDistPN->GetSize() );
 
@@ -380,7 +380,7 @@ bool DIALOG_EXPORT_2581::TransferDataFromWindow()
     }
     else
     {
-        m_job->SetOutputPath( m_outputFileName->GetValue() );
+        m_job->SetConfiguredOutputPath( m_outputFileName->GetValue() );
 
         m_job->m_colInternalId = GetOEM();
         m_job->m_colDist = GetDist();
diff --git a/pcbnew/dialogs/dialog_export_odbpp.cpp b/pcbnew/dialogs/dialog_export_odbpp.cpp
index b26bf90922..0e21f61f50 100644
--- a/pcbnew/dialogs/dialog_export_odbpp.cpp
+++ b/pcbnew/dialogs/dialog_export_odbpp.cpp
@@ -92,7 +92,7 @@ DIALOG_EXPORT_ODBPP::DIALOG_EXPORT_ODBPP( JOB_EXPORT_PCB_ODB* aJob, PCB_EDIT_FRA
 
     SetupStandardButtons();
 
-    m_outputFileName->SetValue( m_job->GetOutputPath() );
+    m_outputFileName->SetValue( m_job->GetConfiguredOutputPath() );
 
     // Fill wxChoice (and others) items with data before calling finishDialogSettings()
     // to calculate suitable widgets sizes
@@ -250,7 +250,7 @@ bool DIALOG_EXPORT_ODBPP::Init()
         m_choiceUnits->SetSelection( static_cast<int>( m_job->m_units ) );
         m_precision->SetValue( m_job->m_precision );
         m_choiceCompress->SetSelection( static_cast<int>( m_job->m_compressionMode ) );
-        m_outputFileName->SetValue( m_job->GetOutputPath() );
+        m_outputFileName->SetValue( m_job->GetConfiguredOutputPath() );
     }
 
     // DIALOG_SHIM needs a unique hash_key because classname will be the same for both job and
@@ -274,7 +274,7 @@ bool DIALOG_EXPORT_ODBPP::TransferDataFromWindow()
     }
     else
     {
-        m_job->SetOutputPath( m_outputFileName->GetValue() );
+        m_job->SetConfiguredOutputPath( m_outputFileName->GetValue() );
 
         m_job->m_precision = m_precision->GetValue();
         m_job->m_units =
diff --git a/pcbnew/dialogs/dialog_export_step.cpp b/pcbnew/dialogs/dialog_export_step.cpp
index 58abc792e3..f1bf73c447 100644
--- a/pcbnew/dialogs/dialog_export_step.cpp
+++ b/pcbnew/dialogs/dialog_export_step.cpp
@@ -236,7 +236,7 @@ DIALOG_EXPORT_STEP::DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aEditFrame, wxWindow* aP
         m_cbOverwriteFile->SetValue( m_job->m_3dparams.m_Overwrite );
 
         m_txtComponentFilter->SetValue( m_job->m_3dparams.m_ComponentFilter );
-        m_outputFileName->SetValue( m_job->GetOutputPath() );
+        m_outputFileName->SetValue( m_job->GetConfiguredOutputPath() );
 
         wxCommandEvent dummy;
         DIALOG_EXPORT_STEP::onCbExportComponents( dummy );
@@ -787,7 +787,7 @@ void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
     }
     else
     {
-        m_job->SetOutputPath( m_outputFileName->GetValue() );
+        m_job->SetConfiguredOutputPath( m_outputFileName->GetValue() );
         m_job->m_3dparams.m_NetFilter = m_txtNetFilter->GetValue();
         m_job->m_3dparams.m_ComponentFilter = m_txtComponentFilter->GetValue();
         m_job->m_3dparams.m_ExportBoardBody = m_cbExportBody->GetValue();
diff --git a/pcbnew/dialogs/dialog_gen_footprint_position.cpp b/pcbnew/dialogs/dialog_gen_footprint_position.cpp
index 6cdff6910f..a13ac6aa6a 100644
--- a/pcbnew/dialogs/dialog_gen_footprint_position.cpp
+++ b/pcbnew/dialogs/dialog_gen_footprint_position.cpp
@@ -117,7 +117,7 @@ void DIALOG_GEN_FOOTPRINT_POSITION::initDialog()
         m_units = m_job->m_units == JOB_EXPORT_PCB_POS::UNITS::INCHES ? EDA_UNITS::INCHES
 																	  : EDA_UNITS::MILLIMETRES;
 
-        m_outputDirectoryName->SetValue( m_job->GetOutputPath() );
+        m_outputDirectoryName->SetValue( m_job->GetConfiguredOutputPath() );
 
         m_unitsCtrl->SetSelection( static_cast<int>( m_job->m_units ) );
         m_formatCtrl->SetSelection( static_cast<int>( m_job->m_format ) );
@@ -291,7 +291,7 @@ void DIALOG_GEN_FOOTPRINT_POSITION::onGenerate( wxCommandEvent& event )
     }
     else
     {
-        m_job->SetOutputPath( m_outputDirectoryName->GetValue() );
+        m_job->SetConfiguredOutputPath( m_outputDirectoryName->GetValue() );
         m_job->m_units = m_unitsCtrl->GetSelection() == 0 ? JOB_EXPORT_PCB_POS::UNITS::INCHES
                                                           : JOB_EXPORT_PCB_POS::UNITS::MILLIMETERS;
         m_job->m_format = static_cast<JOB_EXPORT_PCB_POS::FORMAT>( m_formatCtrl->GetSelection() );
diff --git a/pcbnew/dialogs/dialog_gendrill.cpp b/pcbnew/dialogs/dialog_gendrill.cpp
index 058ee18467..41be31a3d7 100644
--- a/pcbnew/dialogs/dialog_gendrill.cpp
+++ b/pcbnew/dialogs/dialog_gendrill.cpp
@@ -133,7 +133,7 @@ bool DIALOG_GENDRILL::TransferDataFromWindow()
     }
     else
     {
-        m_job->SetOutputPath( m_outputDirectoryName->GetValue() );
+        m_job->SetConfiguredOutputPath( m_outputDirectoryName->GetValue() );
         m_job->m_format = m_rbExcellon->GetValue() ? JOB_EXPORT_PCB_DRILL::DRILL_FORMAT::EXCELLON
 												   : JOB_EXPORT_PCB_DRILL::DRILL_FORMAT::GERBER;
         m_job->m_drillUnits = m_units->GetSelection() == 0
@@ -178,7 +178,7 @@ bool DIALOG_GENDRILL::TransferDataToWindow()
     else
     {
         m_browseButton->Hide();
-        m_outputDirectoryName->SetValue( m_job->GetOutputPath() );
+        m_outputDirectoryName->SetValue( m_job->GetConfiguredOutputPath() );
 
         m_rbExcellon->SetValue( m_job->m_format == JOB_EXPORT_PCB_DRILL::DRILL_FORMAT::EXCELLON );
         m_rbGerberX2->SetValue( m_job->m_format == JOB_EXPORT_PCB_DRILL::DRILL_FORMAT::GERBER );
diff --git a/pcbnew/dialogs/dialog_plot.cpp b/pcbnew/dialogs/dialog_plot.cpp
index 5b309d80bf..39a0fe7258 100644
--- a/pcbnew/dialogs/dialog_plot.cpp
+++ b/pcbnew/dialogs/dialog_plot.cpp
@@ -520,7 +520,7 @@ void DIALOG_PLOT::transferPlotParamsToJob()
         }
     }
 
-    m_job->SetOutputPath( m_plotOpts.GetOutputDirectory() );
+    m_job->SetConfiguredOutputPath( m_plotOpts.GetOutputDirectory() );
 }
 
 
diff --git a/pcbnew/dialogs/dialog_render_job.cpp b/pcbnew/dialogs/dialog_render_job.cpp
index 9b66dc7d8b..656ebec9e6 100644
--- a/pcbnew/dialogs/dialog_render_job.cpp
+++ b/pcbnew/dialogs/dialog_render_job.cpp
@@ -151,7 +151,7 @@ void DIALOG_RENDER_JOB::setSelectedBgStyle( JOB_PCB_RENDER::BG_STYLE aBgStyle )
 
 bool DIALOG_RENDER_JOB::TransferDataFromWindow()
 {
-    m_job->SetOutputPath( m_textCtrlOutputFile->GetValue() );
+    m_job->SetConfiguredOutputPath( m_textCtrlOutputFile->GetValue() );
 
     m_job->m_format = getSelectedFormat();
     m_job->m_quality = getSelectedQuality();
@@ -191,7 +191,7 @@ bool DIALOG_RENDER_JOB::TransferDataFromWindow()
 
 bool DIALOG_RENDER_JOB::TransferDataToWindow()
 {
-    m_textCtrlOutputFile->SetValue( m_job->GetOutputPath() );
+    m_textCtrlOutputFile->SetValue( m_job->GetConfiguredOutputPath() );
 
     setSelectedFormat( m_job->m_format );
     setSelectedBgStyle( m_job->m_bgStyle );
diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp
index 915c5267ff..f949bdff51 100644
--- a/pcbnew/files.cpp
+++ b/pcbnew/files.cpp
@@ -1427,7 +1427,7 @@ void PCB_EDIT_FRAME::GenODBPPFiles( wxCommandEvent& event )
 
     JOB_EXPORT_PCB_ODB job;
 
-    job.SetOutputPath( dlg.GetOutputPath() );
+    job.SetConfiguredOutputPath( dlg.GetOutputPath() );
     job.m_filename = GetBoard()->GetFileName();
     job.m_compressionMode = static_cast<JOB_EXPORT_PCB_ODB::ODB_COMPRESSION>( dlg.GetCompressFormat() );
 
diff --git a/pcbnew/pcb_plotter.cpp b/pcbnew/pcb_plotter.cpp
index 3563836315..38fcbc4f56 100644
--- a/pcbnew/pcb_plotter.cpp
+++ b/pcbnew/pcb_plotter.cpp
@@ -421,5 +421,5 @@ void PCB_PLOTTER::PlotJobToPlotOpts( PCB_PLOT_PARAMS& aPlotOpts, JOB_EXPORT_PCB_
     PCBNEW_SETTINGS* cfg = mgr.GetAppSettings<PCBNEW_SETTINGS>( theme );
     aPlotOpts.SetColorSettings( mgr.GetColorSettings( cfg->m_ColorTheme ) );
 
-    aPlotOpts.SetOutputDirectory( aJob->GetOutputPath() );
+    aPlotOpts.SetOutputDirectory( aJob->GetConfiguredOutputPath() );
 }
\ No newline at end of file
diff --git a/pcbnew/pcbnew_jobs_handler.cpp b/pcbnew/pcbnew_jobs_handler.cpp
index b24b48d0df..6e3cec74b9 100644
--- a/pcbnew/pcbnew_jobs_handler.cpp
+++ b/pcbnew/pcbnew_jobs_handler.cpp
@@ -333,7 +333,7 @@ int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob )
     brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
     brd->SynchronizeProperties();
 
-    if( aStepJob->GetOutputPath().IsEmpty() )
+    if( aStepJob->GetConfiguredOutputPath().IsEmpty() )
     {
         wxFileName fn = brd->GetFileName();
         fn.SetName( fn.GetName() );
@@ -359,7 +359,7 @@ int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob )
             return CLI::EXIT_CODES::ERR_UNKNOWN; // shouldnt have gotten here
         }
 
-        aStepJob->SetOutputPath( fn.GetFullName() );
+        aStepJob->SetWorkingOutputPath( fn.GetFullName() );
     }
 
     wxString outPath = aStepJob->GetFullOutputPath( brd->GetProject() );
@@ -476,7 +476,7 @@ int PCBNEW_JOBS_HANDLER::JobExportRender( JOB* aJob )
     brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
     brd->SynchronizeProperties();
 
-    if( aRenderJob->GetOutputPath().IsEmpty() )
+    if( aRenderJob->GetConfiguredOutputPath().IsEmpty() )
     {
         wxFileName fn = brd->GetFileName();
 
@@ -494,7 +494,7 @@ int PCBNEW_JOBS_HANDLER::JobExportRender( JOB* aJob )
         // or we do a hash based on all the options
         fn.SetName( wxString::Format( "%s-%d", fn.GetName(), static_cast<int>( aRenderJob->m_side ) ) );
 
-        aRenderJob->SetOutputPath( fn.GetFullName() );
+        aRenderJob->SetWorkingOutputPath( fn.GetFullName() );
     }
 
     wxString outPath = aRenderJob->GetFullOutputPath( brd->GetProject() );
@@ -719,13 +719,13 @@ int PCBNEW_JOBS_HANDLER::JobExportSvg( JOB* aJob )
 
     if( aSvgJob->m_genMode == JOB_EXPORT_PCB_SVG::GEN_MODE::SINGLE )
     {
-        if( aSvgJob->GetOutputPath().IsEmpty() )
+        if( aSvgJob->GetConfiguredOutputPath().IsEmpty() )
         {
             wxFileName fn = brd->GetFileName();
             fn.SetName( fn.GetName() );
             fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::SVG ) );
 
-            aSvgJob->SetOutputPath( fn.GetFullName() );
+            aSvgJob->SetWorkingOutputPath( fn.GetFullName() );
         }
     }
 
@@ -796,13 +796,13 @@ int PCBNEW_JOBS_HANDLER::JobExportDxf( JOB* aJob )
 
     if( aDxfJob->m_genMode == JOB_EXPORT_PCB_DXF::GEN_MODE::SINGLE )
     {
-        if( aDxfJob->GetOutputPath().IsEmpty() )
+        if( aDxfJob->GetConfiguredOutputPath().IsEmpty() )
         {
             wxFileName fn = brd->GetFileName();
             fn.SetName( fn.GetName() );
             fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::DXF ) );
 
-            aDxfJob->SetOutputPath( fn.GetFullName() );
+            aDxfJob->SetWorkingOutputPath( fn.GetFullName() );
         }
     }
 
@@ -865,13 +865,13 @@ int PCBNEW_JOBS_HANDLER::JobExportPdf( JOB* aJob )
     brd->SynchronizeProperties();
 
     if( aPdfJob->m_pdfGenMode == JOB_EXPORT_PCB_PDF::GEN_MODE::ALL_LAYERS_ONE_FILE
-        && aPdfJob->GetOutputPath().IsEmpty() )
+        && aPdfJob->GetConfiguredOutputPath().IsEmpty() )
     {
         wxFileName fn = brd->GetFileName();
         fn.SetName( fn.GetName() );
         fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::PDF ) );
 
-        aPdfJob->SetOutputPath( fn.GetFullName() );
+        aPdfJob->SetWorkingOutputPath( fn.GetFullName() );
     }
 
     PCB_PLOT_PARAMS plotOpts;
@@ -1086,13 +1086,13 @@ int PCBNEW_JOBS_HANDLER::JobExportGencad( JOB* aJob )
     exporter.SetPlotOffet( GencadOffset );
     exporter.StoreOriginCoordsInFile( aGencadJob->m_storeOriginCoords );
 
-    if( aGencadJob->GetOutputPath().IsEmpty() )
+    if( aGencadJob->GetConfiguredOutputPath().IsEmpty() )
     {
         wxFileName fn = brd->GetFileName();
         fn.SetName( fn.GetName() );
         fn.SetExt( FILEEXT::GencadFileExtension );
 
-        aGencadJob->SetOutputPath( fn.GetFullName() );
+        aGencadJob->SetWorkingOutputPath( fn.GetFullName() );
     }
 
     wxString outPath = aGencadJob->GetFullOutputPath( brd->GetProject() );
@@ -1159,13 +1159,13 @@ int PCBNEW_JOBS_HANDLER::JobExportGerber( JOB* aJob )
     brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
     brd->SynchronizeProperties();
 
-    if( aGerberJob->GetOutputPath().IsEmpty() )
+    if( aGerberJob->GetConfiguredOutputPath().IsEmpty() )
     {
         wxFileName fn = brd->GetFileName();
         fn.SetName( fn.GetName() );
         fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::GERBER ) );
 
-        aGerberJob->SetOutputPath( fn.GetFullName() );
+        aGerberJob->SetWorkingOutputPath( fn.GetFullName() );
     }
 
     PCB_PLOT_PARAMS plotOpts;
@@ -1357,7 +1357,7 @@ int PCBNEW_JOBS_HANDLER::JobExportPos( JOB* aJob )
 
     aJob->SetTitleBlock( brd->GetTitleBlock() );
 
-    if( aPosJob->GetOutputPath().IsEmpty() )
+    if( aPosJob->GetConfiguredOutputPath().IsEmpty() )
     {
         wxFileName fn = brd->GetFileName();
         fn.SetName( fn.GetName() );
@@ -1369,7 +1369,7 @@ int PCBNEW_JOBS_HANDLER::JobExportPos( JOB* aJob )
         else if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::GERBER )
             fn.SetExt( FILEEXT::GerberFileExtension );
 
-        aPosJob->SetOutputPath( fn.GetFullName() );
+        aPosJob->SetWorkingOutputPath( fn.GetFullName() );
     }
 
     wxString outPath = aPosJob->GetFullOutputPath( brd->GetProject() );
@@ -1680,7 +1680,7 @@ int PCBNEW_JOBS_HANDLER::JobExportDrc( JOB* aJob )
     brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
     brd->SynchronizeProperties();
 
-    if( drcJob->GetOutputPath().IsEmpty() )
+    if( drcJob->GetConfiguredOutputPath().IsEmpty() )
     {
         wxFileName fn = brd->GetFileName();
         fn.SetName( fn.GetName() + wxS( "-drc" ) );
@@ -1690,7 +1690,7 @@ int PCBNEW_JOBS_HANDLER::JobExportDrc( JOB* aJob )
         else
             fn.SetExt( FILEEXT::ReportFileExtension );
 
-        drcJob->SetOutputPath( fn.GetFullName() );
+        drcJob->SetWorkingOutputPath( fn.GetFullName() );
     }
 
     wxString outPath = drcJob->GetFullOutputPath( brd->GetProject() );
@@ -1861,7 +1861,7 @@ int PCBNEW_JOBS_HANDLER::JobExportIpc2581( JOB* aJob )
         fn.SetName( fn.GetName() );
         fn.SetExt( FILEEXT::Ipc2581FileExtension );
 
-        job->SetOutputPath( fn.GetName() );
+        job->SetWorkingOutputPath( fn.GetName() );
     }
 
     wxString outPath = job->GetFullOutputPath( brd->GetProject() );
@@ -1950,14 +1950,14 @@ int PCBNEW_JOBS_HANDLER::JobExportOdb( JOB* aJob )
 
     aJob->SetTitleBlock( brd->GetTitleBlock() );
 
-    wxString   path = job->GetOutputPath();
+    wxString   path = job->GetConfiguredOutputPath();
 
     if( !job->OutputPathFullSpecified() )
     {
         if( job->m_compressionMode == JOB_EXPORT_PCB_ODB::ODB_COMPRESSION::NONE )
         {
             // just basic folder name
-            job->SetOutputPath( "odb" );
+            job->SetWorkingOutputPath( "odb" );
         }
         else
         {
@@ -1975,7 +1975,7 @@ int PCBNEW_JOBS_HANDLER::JobExportOdb( JOB* aJob )
             default: break;
             };
 
-            job->SetOutputPath( fn.GetFullName() );
+            job->SetWorkingOutputPath( fn.GetFullName() );
         }
     }