From d74caace0ad17fe60971f4acf140f866fcdcd754 Mon Sep 17 00:00:00 2001
From: Marek Roszko <mark.roszko@gmail.com>
Date: Mon, 15 Jul 2024 18:20:13 -0400
Subject: [PATCH] Initial jobset creation and running within the CLI and GUI.

Incomplete, just pushing this before feature freeze, much fixing left
---
 common/CMakeLists.txt                         |    5 +
 common/advanced_config.cpp                    |    7 +-
 common/eda_base_frame.cpp                     |    2 +-
 common/gestfich.cpp                           |  100 +
 common/jobs/job.cpp                           |  148 +-
 common/jobs/job.h                             |   96 +-
 common/jobs/job_dispatcher.cpp                |   18 +-
 common/jobs/job_dispatcher.h                  |    9 +-
 common/jobs/job_export_pcb_3d.cpp             |   76 +-
 common/jobs/job_export_pcb_3d.h               |    6 +-
 common/jobs/job_export_pcb_drill.cpp          |   94 +-
 common/jobs/job_export_pcb_drill.h            |    3 +-
 common/jobs/job_export_pcb_dxf.cpp            |   44 +-
 common/jobs/job_export_pcb_dxf.h              |   13 +-
 common/jobs/job_export_pcb_gencad.cpp         |    2 +-
 common/jobs/job_export_pcb_gencad.h           |    2 -
 common/jobs/job_export_pcb_gerber.cpp         |   54 +-
 common/jobs/job_export_pcb_gerber.h           |   15 +-
 common/jobs/job_export_pcb_gerbers.cpp        |   24 +-
 common/jobs/job_export_pcb_gerbers.h          |    1 +
 common/jobs/job_export_pcb_ipc2581.cpp        |   54 +-
 common/jobs/job_export_pcb_ipc2581.h          |    4 +-
 common/jobs/job_export_pcb_pdf.cpp            |   50 +-
 common/jobs/job_export_pcb_pdf.h              |   28 +-
 common/jobs/job_export_pcb_plot.cpp           |   27 +
 common/jobs/job_export_pcb_plot.h             |   72 +
 common/jobs/job_export_pcb_pos.cpp            |   87 +-
 common/jobs/job_export_pcb_pos.h              |    4 +-
 common/jobs/job_export_pcb_svg.cpp            |   49 +-
 common/jobs/job_export_pcb_svg.h              |   24 +-
 common/jobs/job_export_sch_bom.cpp            |   48 +-
 common/jobs/job_export_sch_bom.h              |    2 +-
 common/jobs/job_export_sch_netlist.cpp        |   44 +-
 common/jobs/job_export_sch_netlist.h          |    7 +-
 common/jobs/job_export_sch_plot.cpp           |  133 +-
 common/jobs/job_export_sch_plot.h             |   38 +-
 common/jobs/job_export_sch_pythonbom.cpp      |   19 +-
 common/jobs/job_export_sch_pythonbom.h        |    2 +-
 common/jobs/job_fp_export_svg.cpp             |    3 +-
 common/jobs/job_fp_upgrade.cpp                |    3 +-
 common/jobs/job_pcb_drc.cpp                   |   32 +-
 common/jobs/job_pcb_drc.h                     |    1 +
 common/jobs/job_pcb_render.cpp                |    2 +-
 common/jobs/job_registry.cpp                  |   53 +
 common/jobs/job_registry.h                    |   70 +
 common/jobs/job_sch_erc.cpp                   |   30 +-
 common/jobs/job_sch_erc.h                     |    1 +
 common/jobs/job_sym_export_svg.cpp            |    3 +-
 common/jobs/job_sym_upgrade.cpp               |    2 +-
 common/jobs/jobs_output.h                     |   48 +
 common/jobs/jobs_output_archive.cpp           |   76 +
 common/jobs/jobs_output_archive.h             |   45 +
 common/jobs/jobs_output_folder.cpp            |   61 +
 common/jobs/jobs_output_folder.h              |   35 +
 common/jobs/jobset.cpp                        |  218 +
 common/jobs/jobset.h                          |  111 +
 common/jobs/lset_json.h                       |   34 +
 common/kiway.cpp                              |    8 +
 common/lset.cpp                               |    6 +
 common/project/project_local_settings.cpp     |    2 +-
 common/settings/settings_manager.cpp          |    6 +
 common/wildcards_and_files_ext.cpp            |    7 +
 eeschema/dialogs/dialog_export_netlist.cpp    |  127 +-
 eeschema/dialogs/dialog_export_netlist.h      |    5 +-
 .../dialogs/dialog_export_netlist_base.cpp    |   17 +-
 .../dialogs/dialog_export_netlist_base.fbp    |  230 +-
 eeschema/dialogs/dialog_export_netlist_base.h |   18 +-
 eeschema/dialogs/dialog_plot_schematic.cpp    |  194 +-
 eeschema/dialogs/dialog_plot_schematic.h      |    7 +-
 eeschema/eeschema.cpp                         |    8 +
 eeschema/eeschema_helpers.cpp                 |   27 +-
 eeschema/eeschema_helpers.h                   |    4 +-
 eeschema/eeschema_jobs_handler.cpp            |  176 +-
 eeschema/eeschema_jobs_handler.h              |    3 +
 include/advanced_config.h                     |    9 +
 include/cli/exit_codes.h                      |   17 +-
 include/gestfich.h                            |   25 +
 include/kiway.h                               |   10 +-
 include/lset.h                                |    1 +
 include/settings/settings_manager.h           |    6 +
 include/wildcards_and_files_ext.h             |    3 +
 kicad/CMakeLists.txt                          |    7 +
 kicad/cli/command_jobset.h                    |   37 +
 kicad/cli/command_jobset_run.cpp              |  102 +
 kicad/cli/command_jobset_run.h                |   35 +
 kicad/cli/command_pcb_export_3d.cpp           |    2 +-
 kicad/cli/command_pcb_export_drill.cpp        |    6 +-
 kicad/cli/command_pcb_export_dxf.cpp          |    4 +-
 kicad/cli/command_pcb_export_gencad.cpp       |    1 -
 kicad/cli/command_pcb_export_gerber.cpp       |    4 +-
 kicad/cli/command_pcb_export_ipc2581.cpp      |    2 +-
 kicad/cli/command_pcb_export_pdf.cpp          |    4 +-
 kicad/cli/command_pcb_export_pos.cpp          |    2 +-
 kicad/cli/command_pcb_export_svg.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         |    5 +-
 kicad/cli/command_sch_export_pythonbom.cpp    |    2 +-
 kicad/dialogs/dialog_job_config_base.cpp      |   52 +
 kicad/dialogs/dialog_job_config_base.fbp      |  221 +
 kicad/dialogs/dialog_job_config_base.h        |   49 +
 kicad/dialogs/panel_jobs.cpp                  |  569 +++
 kicad/dialogs/panel_jobs.h                    |   61 +
 kicad/dialogs/panel_jobs_base.cpp             |  249 ++
 kicad/dialogs/panel_jobs_base.fbp             | 1799 ++++++++
 kicad/dialogs/panel_jobs_base.h               |  134 +
 kicad/jobs_runner.cpp                         |  169 +
 kicad/jobs_runner.h                           |   40 +
 kicad/kicad_cli.cpp                           |   12 +
 kicad/kicad_id.h                              |    2 +
 kicad/kicad_manager_frame.cpp                 |   32 +-
 kicad/kicad_manager_frame.h                   |    2 +
 kicad/menubar.cpp                             |    5 +
 kicad/project_tree.cpp                        |    2 +
 kicad/project_tree_item.cpp                   |    5 +
 kicad/project_tree_pane.cpp                   |   18 +
 kicad/project_tree_pane.h                     |    5 +
 kicad/tools/kicad_manager_actions.cpp         |    7 +
 kicad/tools/kicad_manager_actions.h           |    1 +
 kicad/tools/kicad_manager_control.cpp         |   19 +
 kicad/tools/kicad_manager_control.h           |    1 +
 kicad/tree_file_type.h                        |    1 +
 pcbnew/dialogs/dialog_export_2581.cpp         |  127 +-
 pcbnew/dialogs/dialog_export_2581.h           |    3 +
 pcbnew/dialogs/dialog_export_step.cpp         |  690 +--
 pcbnew/dialogs/dialog_export_step.h           |    4 +
 pcbnew/dialogs/dialog_export_svg.cpp          |   18 +-
 pcbnew/dialogs/dialog_export_svg.h            |   11 +-
 .../dialogs/dialog_gen_footprint_position.cpp |  134 +-
 .../dialogs/dialog_gen_footprint_position.h   |    3 +
 pcbnew/dialogs/dialog_gendrill.cpp            |  148 +-
 pcbnew/dialogs/dialog_gendrill.h              |    8 +
 pcbnew/dialogs/dialog_gendrill_base.cpp       |    4 +-
 pcbnew/dialogs/dialog_gendrill_base.fbp       | 3936 +++++++++--------
 pcbnew/dialogs/dialog_gendrill_base.h         |    5 +-
 pcbnew/dialogs/dialog_plot.cpp                |  758 ++--
 pcbnew/dialogs/dialog_plot.h                  |   12 +-
 pcbnew/exporters/export_gencad_writer.cpp     |    2 +-
 pcbnew/exporters/export_gencad_writer.h       |    2 +-
 pcbnew/exporters/gerber_placefile_writer.cpp  |    2 +-
 pcbnew/exporters/gerber_placefile_writer.h    |    2 +-
 pcbnew/pcbnew.cpp                             |    8 +
 pcbnew/pcbnew_jobs_handler.cpp                |  367 +-
 pcbnew/pcbnew_jobs_handler.h                  |    3 +
 .../scripting/pcbnew_scripting_helpers.cpp    |   32 +-
 .../scripting/pcbnew_scripting_helpers.h      |    8 +-
 pcbnew/tools/board_editor_control.cpp         |    2 +-
 qa/tests/CMakeLists.txt                       |   11 +
 qa/tests/cli/test_sch.py                      |    2 +-
 resources/schemas/jobs.v1.json                |   66 +
 150 files changed, 9950 insertions(+), 3247 deletions(-)
 create mode 100644 common/jobs/job_export_pcb_plot.cpp
 create mode 100644 common/jobs/job_export_pcb_plot.h
 create mode 100644 common/jobs/job_registry.cpp
 create mode 100644 common/jobs/job_registry.h
 create mode 100644 common/jobs/jobs_output.h
 create mode 100644 common/jobs/jobs_output_archive.cpp
 create mode 100644 common/jobs/jobs_output_archive.h
 create mode 100644 common/jobs/jobs_output_folder.cpp
 create mode 100644 common/jobs/jobs_output_folder.h
 create mode 100644 common/jobs/jobset.cpp
 create mode 100644 common/jobs/jobset.h
 create mode 100644 common/jobs/lset_json.h
 create mode 100644 kicad/cli/command_jobset.h
 create mode 100644 kicad/cli/command_jobset_run.cpp
 create mode 100644 kicad/cli/command_jobset_run.h
 create mode 100644 kicad/dialogs/dialog_job_config_base.cpp
 create mode 100644 kicad/dialogs/dialog_job_config_base.fbp
 create mode 100644 kicad/dialogs/dialog_job_config_base.h
 create mode 100644 kicad/dialogs/panel_jobs.cpp
 create mode 100644 kicad/dialogs/panel_jobs.h
 create mode 100644 kicad/dialogs/panel_jobs_base.cpp
 create mode 100644 kicad/dialogs/panel_jobs_base.fbp
 create mode 100644 kicad/dialogs/panel_jobs_base.h
 create mode 100644 kicad/jobs_runner.cpp
 create mode 100644 kicad/jobs_runner.h
 create mode 100644 resources/schemas/jobs.v1.json

diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index cfc7af82d7..c393fe0e0e 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -61,12 +61,16 @@ set( KICOMMON_SRCS
     gal/color4d.cpp
     # Jobs
     jobs/job.cpp
+    jobs/job_registry.cpp
+    jobs/jobs_output_archive.cpp
+    jobs/jobs_output_folder.cpp
     jobs/job_export_pcb_drill.cpp
     jobs/job_export_pcb_dxf.cpp
     jobs/job_export_pcb_gerber.cpp
     jobs/job_export_pcb_gerbers.cpp
     jobs/job_export_pcb_ipc2581.cpp
     jobs/job_export_pcb_pdf.cpp
+    jobs/job_export_pcb_plot.cpp
     jobs/job_export_pcb_pos.cpp
     jobs/job_export_pcb_svg.cpp
     jobs/job_export_pcb_gencad.cpp
@@ -75,6 +79,7 @@ set( KICOMMON_SRCS
     jobs/job_export_sch_netlist.cpp
     jobs/job_export_sch_plot.cpp
     jobs/job_export_sch_pythonbom.cpp
+    jobs/jobset.cpp
     jobs/job_fp_export_svg.cpp
     jobs/job_fp_upgrade.cpp
     jobs/job_pcb_render.cpp
diff --git a/common/advanced_config.cpp b/common/advanced_config.cpp
index d135e64159..058b455704 100644
--- a/common/advanced_config.cpp
+++ b/common/advanced_config.cpp
@@ -120,6 +120,7 @@ static const wxChar ResolveTextRecursionDepth[] = wxT( "ResolveTextRecursionDept
 static const wxChar EnableExtensionSnaps[] = wxT( "EnableExtensionSnaps" );
 static const wxChar EnableSnapAnchorsDebug[] = wxT( "EnableSnapAnchorsDebug" );
 static const wxChar EnableODB[] = wxT( "EnableODB" );
+static const wxChar EnableJobset[] = wxT( "EnableJobset" );
 } // namespace KEYS
 
 
@@ -248,6 +249,7 @@ ADVANCED_CFG::ADVANCED_CFG()
     m_EnableDesignBlocks        = false;
     m_EnableGenerators          = false;
     m_EnableGit                 = false;
+    m_EnableJobset              = false;
     m_EnableLibWithText         = false;
     m_EnableLibDir              = false;
 
@@ -479,6 +481,9 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
     configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableGit,
                                                 &m_EnableGit, m_EnableGit ) );
 
+    configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableJobset,
+                                                &m_EnableJobset, m_EnableJobset ) );
+
     configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableLibWithText,
                                                 &m_EnableLibWithText, m_EnableLibWithText ) );
 
@@ -528,7 +533,7 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
     configParams.push_back( new PARAM_CFG_INT( true, AC_KEYS::ResolveTextRecursionDepth,
                                                   &m_ResolveTextRecursionDepth,
                                                   m_ResolveTextRecursionDepth, 0, 10 ) );
-    
+
     configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::EnableODB,
                                             &m_EnableODB, m_EnableODB ) );
 
diff --git a/common/eda_base_frame.cpp b/common/eda_base_frame.cpp
index c6a183390b..fa6a126c16 100644
--- a/common/eda_base_frame.cpp
+++ b/common/eda_base_frame.cpp
@@ -274,7 +274,7 @@ EDA_BASE_FRAME::~EDA_BASE_FRAME()
     Disconnect( ID_AUTO_SAVE_TIMER, wxEVT_TIMER,
              wxTimerEventHandler( EDA_BASE_FRAME::onAutoSaveTimer ) );
     Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( EDA_BASE_FRAME::windowClosing ) );
-    
+
     delete m_autoSaveTimer;
     delete m_fileHistory;
 
diff --git a/common/gestfich.cpp b/common/gestfich.cpp
index 04c0cef3ce..d4700a1c6a 100644
--- a/common/gestfich.cpp
+++ b/common/gestfich.cpp
@@ -39,6 +39,10 @@
 #include <launch_ext.h>
 #include "wx/tokenzr.h"
 
+#include <wx/wfstream.h>
+#include <wx/fs_zip.h>
+#include <wx/zipstrm.h>
+
 #include <filesystem>
 
 void QuoteString( wxString& string )
@@ -369,3 +373,99 @@ bool RmDirRecursive( const wxString& aFileName, wxString* aErrors )
 
     return true;
 }
+
+bool CopyDirectory( const wxString& aSourceDir, const wxString& aDestDir, wxString& aErrors )
+{
+    wxDir dir( aSourceDir );
+    if( !dir.IsOpened() )
+    {
+        aErrors += wxString::Format( _( "Could not open source directory: %s" ), aSourceDir );
+        aErrors += wxT( "\n" );
+        return false;
+    }
+
+    if( !wxFileName::Mkdir( aDestDir, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
+    {
+        aErrors += wxString::Format( _( "Could not create destination directory: %s" ), aDestDir );
+        aErrors += wxT( "\n" );
+        return false;
+    }
+
+    wxString filename;
+    bool     cont = dir.GetFirst( &filename );
+    while( cont )
+    {
+        wxString sourcePath = aSourceDir + wxFileName::GetPathSeparator() + filename;
+        wxString destPath = aDestDir + wxFileName::GetPathSeparator() + filename;
+
+        if( wxFileName::DirExists( sourcePath ) )
+        {
+            // Recursively copy subdirectories
+            if( !CopyDirectory( sourcePath, destPath, aErrors ) )
+            {
+                return false;
+            }
+        }
+        else
+        {
+            // Copy files
+            if( !wxCopyFile( sourcePath, destPath ) )
+            {
+                aErrors += wxString::Format( _( "Could not copy file: %s to %s" ), sourcePath, destPath );
+                return false;
+            }
+        }
+
+        cont = dir.GetNext( &filename );
+    }
+
+    return true;
+}
+
+
+bool AddDirectoryToZip( wxZipOutputStream& aZip, const wxString& aSourceDir, wxString& aErrors,
+                        const wxString& aParentDir )
+{
+    wxDir dir( aSourceDir );
+    if( !dir.IsOpened() )
+    {
+        aErrors += wxString::Format( _( "Could not open source directory: %s" ), aSourceDir );
+        aErrors += "\n";
+        return false;
+    }
+
+    wxString filename;
+    bool     cont = dir.GetFirst( &filename );
+    while( cont )
+    {
+        wxString sourcePath = aSourceDir + wxFileName::GetPathSeparator() + filename;
+        wxString zipPath = aParentDir + filename;
+
+        if( wxFileName::DirExists( sourcePath ) )
+        {
+            // Add directory entry to the ZIP file
+            aZip.PutNextDirEntry( zipPath + "/" );
+            // Recursively add subdirectories
+            if( !AddDirectoryToZip( aZip, sourcePath, aErrors, zipPath + "/" ) )
+            {
+                return false;
+            }
+        }
+        else
+        {
+            // Add file entry to the ZIP file
+            aZip.PutNextEntry( zipPath );
+            wxFFileInputStream fileStream( sourcePath );
+            if( !fileStream.IsOk() )
+            {
+                aErrors += wxString::Format( _( "Could not read file: %s" ), sourcePath );
+                return false;
+            }
+            aZip.Write( fileStream );
+        }
+
+        cont = dir.GetNext( &filename );
+    }
+
+    return true;
+}
\ No newline at end of file
diff --git a/common/jobs/job.cpp b/common/jobs/job.cpp
index fa3678f76c..3edb4257a4 100644
--- a/common/jobs/job.cpp
+++ b/common/jobs/job.cpp
@@ -2,7 +2,7 @@
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
  * Copyright (C) 2023 Mark Roszko <mark.roszko@gmail.com>
- * Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
+ * Copyright (C) 2024 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
@@ -19,10 +19,152 @@
  */
 
 #include <jobs/job.h>
+#include <wx/filename.h>
 
-JOB::JOB( const std::string& aType, bool aIsCli ) :
+JOB::JOB( const std::string& aType, bool aOutputIsDirectory, bool aIsCli ) :
         m_type( aType ),
         m_isCli( aIsCli ),
-        m_varOverrides()
+        m_varOverrides(),
+        m_tempOutputDirectory(),
+        m_outputPath(),
+        m_outputPathIsDirectory( aOutputIsDirectory )
+{
+    if( m_outputPathIsDirectory )
+    {
+        m_params.emplace_back(
+                new JOB_PARAM<wxString>( "output_dir", &m_outputPath, m_outputPath ) );
+    }
+    else
+    {
+        m_params.emplace_back(
+                new JOB_PARAM<wxString>( "output_filename", &m_outputPath, m_outputPath ) );
+    }
+}
+
+
+JOB::~JOB()
+{
+    for( JOB_PARAM_BASE* param : m_params )
+        delete param;
+
+    m_params.clear();
+}
+
+
+void JOB::FromJson( const nlohmann::json& j )
+{
+    for( JOB_PARAM_BASE* param : m_params )
+        param->FromJson( j );
+}
+
+
+void JOB::ToJson( nlohmann::json& j ) const
+{
+    for( JOB_PARAM_BASE* param : m_params )
+        param->ToJson( j );
+}
+
+
+wxString JOB::GetDescription()
+{
+    return wxEmptyString;
+}
+
+
+void JOB::SetTempOutputDirectory( const wxString& aBase )
+{
+    m_tempOutputDirectory = aBase;
+}
+
+
+void PrependDirectoryToPath( wxFileName& aFileName, const wxString aDirPath )
+{
+    wxFileName fn( aDirPath + wxFileName::GetPathSeparator() + aFileName.GetFullPath() );
+
+    aFileName = fn;
+}
+
+
+wxString JOB::GetFullOutputPath() const
+{
+    if( !m_tempOutputDirectory.IsEmpty() )
+    {
+        if( m_outputPathIsDirectory )
+        {
+            wxFileName fn( m_outputPath );
+            if( fn.IsAbsolute() || m_outputPath.IsEmpty() )
+            {
+                fn.AssignDir( m_tempOutputDirectory );
+            }
+            else
+            {
+                PrependDirectoryToPath( fn, m_tempOutputDirectory );
+            }
+
+
+            return fn.GetFullPath();
+        }
+        else
+        {
+            wxFileName fn( m_outputPath );
+            if( fn.IsAbsolute() || m_outputPath.IsEmpty() )
+            {
+                // uhhh, do nothing
+                // either its a full path passed by cli, so we return as-is
+                // or it's a empty path from either...in which case things will fail but who cares
+                // the job handlers should have fixed empty paths
+            }
+            else
+            {
+                PrependDirectoryToPath( fn, m_tempOutputDirectory );
+            }
+
+            return fn.GetFullPath();
+        }
+	}
+
+    return m_outputPath;
+}
+
+
+void JOB::SetOutputPath( const wxString& aPath )
+{
+    m_outputPath = aPath;
+}
+
+
+bool JOB::OutputPathFullSpecified() const
+{
+    if( m_outputPath.IsEmpty() )
+    {
+        return false;
+    }
+
+    wxFileName fn( m_outputPath );
+    if( m_outputPathIsDirectory )
+    {
+        return fn.IsDir();
+    }
+    else
+    {
+        return !fn.IsDir();
+    }
+}
+
+
+KICOMMON_API void to_json( nlohmann::json& j, const JOB& f )
+{
+    f.ToJson( j );
+}
+
+
+KICOMMON_API void from_json( const nlohmann::json& j, JOB& f )
+{
+    f.FromJson( j );
+}
+
+
+JOB_PARAM_BASE::JOB_PARAM_BASE( const std::string& aJsonPath ) :
+        m_jsonPath( aJsonPath )
 {
 }
\ No newline at end of file
diff --git a/common/jobs/job.h b/common/jobs/job.h
index 47e24e47f6..bfcf6cb23a 100644
--- a/common/jobs/job.h
+++ b/common/jobs/job.h
@@ -2,7 +2,7 @@
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
  * Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
- * Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
+ * Copyright (C) 1992-2024 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
@@ -18,12 +18,55 @@
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef JOB_H
-#define JOB_H
+#pragma once
 
 #include <kicommon.h>
 #include <map>
 #include <wx/string.h>
+#include <settings/json_settings.h>
+
+class KICOMMON_API JOB_PARAM_BASE
+{
+public:
+    JOB_PARAM_BASE( const std::string& aJsonPath );
+
+    virtual ~JOB_PARAM_BASE() = default;
+
+    virtual void FromJson( const nlohmann::json& j ) const = 0;
+
+    virtual void ToJson( nlohmann::json& j ) = 0;
+
+protected:
+    std::string m_jsonPath;
+};
+
+template <typename ValueType>
+class JOB_PARAM : public JOB_PARAM_BASE
+{
+public:
+
+    JOB_PARAM( const std::string& aJsonPath, ValueType* aPtr,
+               ValueType aDefault ) :
+            JOB_PARAM_BASE( aJsonPath ), m_ptr( aPtr ), m_default( aDefault )
+    {
+    }
+
+    virtual void FromJson( const nlohmann::json& j ) const override
+    {
+        *m_ptr = j.value( m_jsonPath, m_default );
+    }
+
+    virtual void ToJson( nlohmann::json& j ) override { j[m_jsonPath] = *m_ptr; }
+
+protected:
+    ValueType* m_ptr;
+    ValueType  m_default;
+};
+
+struct KICOMMON_API JOB_OUTPUT
+{
+    wxString m_outputPath;
+};
 
 /**
  * An simple container class that lets us dispatch output jobs to kifaces
@@ -31,9 +74,9 @@
 class KICOMMON_API JOB
 {
 public:
-    JOB( const std::string& aType, bool aIsCli );
+    JOB( const std::string& aType, bool aOutputIsDirectory, bool aIsCli );
 
-    virtual ~JOB() {}
+    virtual ~JOB();
 
     const std::string& GetType() const { return m_type; };
     bool IsCli() const { return m_isCli; };
@@ -45,10 +88,51 @@ public:
         m_varOverrides = aVarOverrides;
     }
 
+    virtual void FromJson( const nlohmann::json& j );
+    virtual void ToJson( nlohmann::json& j ) const;
+
+    virtual wxString GetDescription();
+
+    const std::vector<JOB_PARAM_BASE*>& GetParams() {
+        return m_params;
+    }
+
+    void ClearExistingOutputs() {
+        m_outputs.clear();
+    }
+
+    const std::vector<JOB_OUTPUT>& GetOutputs() {
+        return m_outputs;
+    }
+
+    void AddOutput( wxString aOutputPath ) {
+        m_outputs.emplace_back( aOutputPath );
+    }
+
+    void SetTempOutputDirectory( const wxString& aBase );
+
+
+    void SetOutputPath( const wxString& aPath );
+    wxString GetOutputPath() const { return m_outputPath; }
+    wxString GetFullOutputPath() const;
+
+    bool OutputPathFullSpecified() const;
+
+
 protected:
     std::string m_type;
     bool m_isCli;
     std::map<wxString, wxString> m_varOverrides;
+
+    wxString m_tempOutputDirectory;
+
+    wxString m_outputPath;
+    bool m_outputPathIsDirectory;
+
+    std::vector<JOB_PARAM_BASE*> m_params;
+
+    std::vector<JOB_OUTPUT> m_outputs;
 };
 
-#endif
\ No newline at end of file
+KICOMMON_API void from_json( const nlohmann::json& j, JOB& f );
+KICOMMON_API void to_json( nlohmann::json& j, const JOB& f );
\ No newline at end of file
diff --git a/common/jobs/job_dispatcher.cpp b/common/jobs/job_dispatcher.cpp
index 0713ac32dd..e2e5eb1959 100644
--- a/common/jobs/job_dispatcher.cpp
+++ b/common/jobs/job_dispatcher.cpp
@@ -23,6 +23,7 @@
 #include <reporter.h>
 #include <wx/debug.h>
 
+class wxWindow;
 
 JOB_DISPATCHER::JOB_DISPATCHER( KIWAY* aKiway ) :
         m_kiway( aKiway )
@@ -33,14 +34,18 @@ JOB_DISPATCHER::JOB_DISPATCHER( KIWAY* aKiway ) :
 
 
 void JOB_DISPATCHER::Register( const std::string&             aJobTypeName,
-                               std::function<int( JOB* job )> aHandler )
+                               std::function<int( JOB* job )> aHandler,
+                               std::function<bool( JOB* aJob, wxWindow* aParent )> aConfigHandler )
 {
     m_jobHandlers.emplace( aJobTypeName, aHandler );
+    m_jobConfigHandlers.emplace( aJobTypeName, aConfigHandler );
 }
 
 
 int JOB_DISPATCHER::RunJob( JOB* job )
 {
+    job->ClearExistingOutputs();
+
     if( m_jobHandlers.count( job->GetType() ) )
     {
         return m_jobHandlers[job->GetType()]( job );
@@ -50,6 +55,17 @@ int JOB_DISPATCHER::RunJob( JOB* job )
 }
 
 
+bool JOB_DISPATCHER::HandleJobConfig( JOB* job, wxWindow* aParent )
+{
+    if( m_jobConfigHandlers.count( job->GetType() ) )
+    {
+        return m_jobConfigHandlers[job->GetType()]( job, aParent );
+    }
+
+    return false;
+}
+
+
 void JOB_DISPATCHER::SetReporter( REPORTER* aReporter )
 {
     wxCHECK( aReporter != nullptr, /*void*/ );
diff --git a/common/jobs/job_dispatcher.h b/common/jobs/job_dispatcher.h
index 45eef27a45..d6368488e1 100644
--- a/common/jobs/job_dispatcher.h
+++ b/common/jobs/job_dispatcher.h
@@ -30,13 +30,16 @@
 class KIWAY;
 class REPORTER;
 class PROGRESS_REPORTER;
+class wxWindow;
 
 class JOB_DISPATCHER
 {
 public:
     JOB_DISPATCHER( KIWAY* aKiway );
-    void Register( const std::string& aJobTypeName, std::function<int( JOB* job )> aHandler );
-    int  RunJob( JOB* job );
+    void Register( const std::string& aJobTypeName, std::function<int( JOB* job )> aHandler,
+                         std::function<bool( JOB* job, wxWindow* aParent )> aConfigHandler );
+    int  RunJob( JOB* aJob );
+    bool HandleJobConfig( JOB* aJob, wxWindow* aParent );
     void SetReporter( REPORTER* aReporter );
     void SetProgressReporter( PROGRESS_REPORTER* aReporter );
 
@@ -47,6 +50,8 @@ protected:
 
 private:
     std::map<std::string, std::function<int( JOB* job )>> m_jobHandlers;
+    std::map<std::string, std::function<bool( JOB* job, wxWindow* aParent )>>
+            m_jobConfigHandlers;
 
 };
 
diff --git a/common/jobs/job_export_pcb_3d.cpp b/common/jobs/job_export_pcb_3d.cpp
index a1c448962e..dd4a7eb91c 100644
--- a/common/jobs/job_export_pcb_3d.cpp
+++ b/common/jobs/job_export_pcb_3d.cpp
@@ -19,7 +19,27 @@
  */
 
 #include <jobs/job_export_pcb_3d.h>
+#include <jobs/job_registry.h>
+#include <i18n_utility.h>
 
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_3D::FORMAT,
+                              {
+                                      { JOB_EXPORT_PCB_3D::FORMAT::UNKNOWN, nullptr },
+                                      { JOB_EXPORT_PCB_3D::FORMAT::STEP, "step" },
+                                      { JOB_EXPORT_PCB_3D::FORMAT::BREP, "brep" },
+                                      { JOB_EXPORT_PCB_3D::FORMAT::GLB, "step" },
+                                      { JOB_EXPORT_PCB_3D::FORMAT::VRML, "vrml" },
+                                      { JOB_EXPORT_PCB_3D::FORMAT::XAO, "xao" },
+                              } )
+
+
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_3D::VRML_UNITS,
+                              {
+                                      { JOB_EXPORT_PCB_3D::VRML_UNITS::INCHES, "in" },
+                                      { JOB_EXPORT_PCB_3D::VRML_UNITS::METERS, "m" },
+                                      { JOB_EXPORT_PCB_3D::VRML_UNITS::MILLIMETERS, "mm" },
+                                      { JOB_EXPORT_PCB_3D::VRML_UNITS::TENTHS, "tenths" },
+                              } )
 
 wxString EXPORTER_STEP_PARAMS::GetDefaultExportExtension() const
 {
@@ -49,7 +69,7 @@ wxString EXPORTER_STEP_PARAMS::GetFormatName() const
 
 
 JOB_EXPORT_PCB_3D::JOB_EXPORT_PCB_3D( bool aIsCli ) :
-    JOB( "3d", aIsCli ),
+    JOB( "3d", false, aIsCli ),
     m_hasUserOrigin( false ),
     m_filename(),
     m_format( JOB_EXPORT_PCB_3D::FORMAT::UNKNOWN ),
@@ -57,4 +77,58 @@ JOB_EXPORT_PCB_3D::JOB_EXPORT_PCB_3D( bool aIsCli ) :
     m_vrmlModelDir( wxEmptyString ),
     m_vrmlRelativePaths( false )
 {
+    m_params.emplace_back(
+            new JOB_PARAM<bool>( "overwrite", &m_3dparams.m_Overwrite, m_3dparams.m_Overwrite ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "use_grid_origin", &m_3dparams.m_UseGridOrigin,
+                                                m_3dparams.m_UseGridOrigin ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "use_drill_origin", &m_3dparams.m_UseDrillOrigin,
+                                                m_3dparams.m_UseDrillOrigin ) );
+    m_params.emplace_back(
+            new JOB_PARAM<bool>( "board_only", &m_3dparams.m_BoardOnly, m_3dparams.m_BoardOnly ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "include_unspecified",
+                                                &m_3dparams.m_IncludeUnspecified,
+                                                m_3dparams.m_IncludeUnspecified ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "include_dnp", &m_3dparams.m_IncludeDNP,
+                                                m_3dparams.m_IncludeDNP ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "subst_models", &m_3dparams.m_SubstModels,
+                                                m_3dparams.m_SubstModels ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "optimize_step", &m_3dparams.m_OptimizeStep,
+                                                m_3dparams.m_OptimizeStep ) );
+    m_params.emplace_back( new JOB_PARAM<double>( "user_origin.x", &m_3dparams.m_Origin.x,
+                                                  m_3dparams.m_Origin.x ) );
+    m_params.emplace_back( new JOB_PARAM<double>( "user_origin.y", &m_3dparams.m_Origin.y,
+                                                  m_3dparams.m_Origin.y ) );
+    m_params.emplace_back( new JOB_PARAM<double>( "board_outlines_chaining_epsilon",
+                                                  &m_3dparams.m_BoardOutlinesChainingEpsilon,
+                                                  m_3dparams.m_BoardOutlinesChainingEpsilon ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "export_board_body", &m_3dparams.m_ExportBoardBody,
+                                                m_3dparams.m_ExportBoardBody ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "export_components", &m_3dparams.m_ExportComponents,
+                                                m_3dparams.m_ExportComponents ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "export_tracks", &m_3dparams.m_ExportTracksVias,
+                                                m_3dparams.m_ExportTracksVias ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "export_pads", &m_3dparams.m_ExportPads,
+                                                m_3dparams.m_ExportPads ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "export_zones", &m_3dparams.m_ExportZones,
+                                                m_3dparams.m_ExportZones ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "export_inner_copper",
+                                                &m_3dparams.m_ExportInnerCopper,
+                                                m_3dparams.m_ExportInnerCopper ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "export_silkscreen", &m_3dparams.m_ExportSilkscreen,
+                                                m_3dparams.m_ExportInnerCopper ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "export_soldermask", &m_3dparams.m_ExportSoldermask,
+                                                m_3dparams.m_ExportSoldermask ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "fuse_shapes", &m_3dparams.m_FuseShapes,
+                                                m_3dparams.m_FuseShapes ) );
+    m_params.emplace_back( new JOB_PARAM<wxString>( "vrml_model_dir", &m_vrmlModelDir, m_vrmlModelDir ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "vrml_relative_paths", &m_vrmlRelativePaths,
+                                                m_vrmlRelativePaths ) );
 }
+
+
+wxString JOB_EXPORT_PCB_3D::GetDescription()
+{
+    return wxString::Format( _( "3D model export" ) );
+}
+
+REGISTER_JOB( pcb_export_3d, _HKI( "PCB: Export 3D Model" ), KIWAY::FACE_PCB, JOB_EXPORT_PCB_3D );
diff --git a/common/jobs/job_export_pcb_3d.h b/common/jobs/job_export_pcb_3d.h
index a30dda4ff4..9192ed1bc2 100644
--- a/common/jobs/job_export_pcb_3d.h
+++ b/common/jobs/job_export_pcb_3d.h
@@ -53,7 +53,8 @@ public:
             m_ExportSoldermask( false ),
             m_FuseShapes( false ),
             m_OptimizeStep( true ),
-            m_Format( FORMAT::STEP )
+            m_Format( FORMAT::STEP ),
+            m_OutputFile()
     {};
 
     enum class FORMAT
@@ -64,7 +65,6 @@ public:
         GLB
     };
 
-    wxString m_OutputFile;
     wxString m_NetFilter;
     wxString m_ComponentFilter;
 
@@ -89,6 +89,7 @@ public:
     bool     m_FuseShapes;
     bool     m_OptimizeStep;
     FORMAT   m_Format;
+    wxString m_OutputFile;
 
     wxString GetDefaultExportExtension() const;
     wxString GetFormatName() const;
@@ -99,6 +100,7 @@ class KICOMMON_API JOB_EXPORT_PCB_3D : public JOB
 {
 public:
     JOB_EXPORT_PCB_3D( bool aIsCli );
+    wxString GetDescription() override;
 
     enum class FORMAT
     {
diff --git a/common/jobs/job_export_pcb_drill.cpp b/common/jobs/job_export_pcb_drill.cpp
index 759fb53ef4..6846bf6231 100644
--- a/common/jobs/job_export_pcb_drill.cpp
+++ b/common/jobs/job_export_pcb_drill.cpp
@@ -19,11 +19,47 @@
  */
 
 #include <jobs/job_export_pcb_drill.h>
+#include <jobs/job_registry.h>
+#include <i18n_utility.h>
+
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_DRILL::DRILL_FORMAT,
+                              {
+                                    { JOB_EXPORT_PCB_DRILL::DRILL_FORMAT::EXCELLON, "excellon" },
+                                    { JOB_EXPORT_PCB_DRILL::DRILL_FORMAT::GERBER, "gerber" },
+                              } )
+
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_DRILL::DRILL_ORIGIN,
+                              {
+                                    { JOB_EXPORT_PCB_DRILL::DRILL_ORIGIN::ABS, "abs" },
+                                    { JOB_EXPORT_PCB_DRILL::DRILL_ORIGIN::PLOT, "plot" },
+                              } )
+
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_DRILL::DRILL_UNITS,
+                              {
+                                    { JOB_EXPORT_PCB_DRILL::DRILL_UNITS::INCHES, "in" },
+                                    { JOB_EXPORT_PCB_DRILL::DRILL_UNITS::MILLIMETERS, "mm" },
+                              } )
+
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_DRILL::ZEROS_FORMAT,
+                              {
+                                    { JOB_EXPORT_PCB_DRILL::ZEROS_FORMAT::DECIMAL, "decimal" },
+                                    { JOB_EXPORT_PCB_DRILL::ZEROS_FORMAT::SUPPRESS_LEADING, "surpress_leading" },
+                                    { JOB_EXPORT_PCB_DRILL::ZEROS_FORMAT::SUPPRESS_TRAILING, "surpress_trailing" },
+                                    { JOB_EXPORT_PCB_DRILL::ZEROS_FORMAT::KEEP_ZEROS, "keep_zeros" },
+                              } )
+
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_DRILL::MAP_FORMAT,
+                              {
+                                      { JOB_EXPORT_PCB_DRILL::MAP_FORMAT::DXF, "dxf" },
+                                      { JOB_EXPORT_PCB_DRILL::MAP_FORMAT::GERBER_X2, "gerberx2" },
+                                      { JOB_EXPORT_PCB_DRILL::MAP_FORMAT::PDF, "pdf" },
+                                      { JOB_EXPORT_PCB_DRILL::MAP_FORMAT::POSTSCRIPT, "postscript" },
+                                      { JOB_EXPORT_PCB_DRILL::MAP_FORMAT::SVG, "svg" },
+                              } )
 
 JOB_EXPORT_PCB_DRILL::JOB_EXPORT_PCB_DRILL( bool aIsCli ) :
-    JOB( "drill", aIsCli ),
+    JOB( "drill", true, aIsCli ),
     m_filename(),
-    m_outputDir(),
     m_excellonMirrorY( false ),
     m_excellonMinimalHeader( false ),
     m_excellonCombinePTHNPTH( true ),
@@ -36,4 +72,56 @@ JOB_EXPORT_PCB_DRILL::JOB_EXPORT_PCB_DRILL( bool aIsCli ) :
     m_gerberPrecision( 5 ),
     m_generateMap( false )
 {
-}
\ No newline at end of file
+    m_params.emplace_back( new JOB_PARAM<bool>( "excellon.mirror_y",
+                                                &m_excellonMirrorY,
+                                                m_excellonMirrorY ) );
+
+    m_params.emplace_back( new JOB_PARAM<bool>( "excellon.minimal_header",
+                                                &m_excellonMinimalHeader,
+                                                m_excellonMinimalHeader ) );
+
+    m_params.emplace_back( new JOB_PARAM<bool>( "excellon.combine_pth_npth",
+                                                &m_excellonCombinePTHNPTH,
+                                                m_excellonCombinePTHNPTH ) );
+
+    m_params.emplace_back( new JOB_PARAM<bool>( "excellon.oval_drill_route",
+                                                &m_excellonOvalDrillRoute,
+                                                m_excellonOvalDrillRoute ) );
+
+    m_params.emplace_back( new JOB_PARAM<DRILL_FORMAT>( "format",
+                                                        &m_format,
+                                                        m_format ) );
+
+    m_params.emplace_back( new JOB_PARAM<DRILL_ORIGIN>( "drill_origin",
+                                                        &m_drillOrigin,
+                                                        m_drillOrigin ) );
+
+    m_params.emplace_back( new JOB_PARAM<DRILL_UNITS>( "units",
+                                                       &m_drillUnits,
+                                                       m_drillUnits ) );
+
+    m_params.emplace_back( new JOB_PARAM<ZEROS_FORMAT>(  "zero_format",
+                                                         &m_zeroFormat,
+                                                         m_zeroFormat ) );
+
+    m_params.emplace_back( new JOB_PARAM<bool>( "generate_map",
+                                                &m_generateMap,
+                                                m_generateMap ) );
+
+    m_params.emplace_back( new JOB_PARAM<MAP_FORMAT>( "map_format",
+                                                      &m_mapFormat,
+                                                      m_mapFormat ) );
+
+    m_params.emplace_back( new JOB_PARAM<int>( "gerber_precision",
+                                               &m_gerberPrecision,
+                                               m_gerberPrecision ) );
+}
+
+
+wxString JOB_EXPORT_PCB_DRILL::GetDescription()
+{
+    return wxString::Format( _( "Drill data export" ), m_format );
+}
+
+REGISTER_JOB( pcb_export_drill, _HKI( "PCB: Export drill data" ), KIWAY::FACE_PCB,
+              JOB_EXPORT_PCB_DRILL );
\ No newline at end of file
diff --git a/common/jobs/job_export_pcb_drill.h b/common/jobs/job_export_pcb_drill.h
index 7423b2ea31..ff5887082e 100644
--- a/common/jobs/job_export_pcb_drill.h
+++ b/common/jobs/job_export_pcb_drill.h
@@ -31,8 +31,9 @@ class KICOMMON_API JOB_EXPORT_PCB_DRILL : public JOB
 public:
     JOB_EXPORT_PCB_DRILL( bool aIsCli );
 
+    wxString GetDescription() override;
+
     wxString m_filename;
-    wxString m_outputDir;
 
     bool m_excellonMirrorY;
     bool m_excellonMinimalHeader;
diff --git a/common/jobs/job_export_pcb_dxf.cpp b/common/jobs/job_export_pcb_dxf.cpp
index 3892cdc773..54b0185d13 100644
--- a/common/jobs/job_export_pcb_dxf.cpp
+++ b/common/jobs/job_export_pcb_dxf.cpp
@@ -19,19 +19,43 @@
  */
 
 #include <jobs/job_export_pcb_dxf.h>
+#include <jobs/job_registry.h>
+#include <i18n_utility.h>
 
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_DXF::DXF_UNITS,
+                              {
+                                      { JOB_EXPORT_PCB_DXF::DXF_UNITS::INCHES, "in" },
+                                      { JOB_EXPORT_PCB_DXF::DXF_UNITS::MILLIMETERS, "mm" },
+                              } )
 
 JOB_EXPORT_PCB_DXF::JOB_EXPORT_PCB_DXF( bool aIsCli ) :
-    JOB( "dxf", aIsCli ),
-    m_filename(),
-    m_outputFile(),
-    m_drawingSheet(),
-    m_plotFootprintValues( true ),
-    m_plotRefDes( true ),
+    JOB_EXPORT_PCB_PLOT( JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::DXF, "dxf", false, aIsCli ),
     m_plotGraphicItemsUsingContours( true ),
     m_useDrillOrigin( false ),
-    m_plotBorderTitleBlocks( false ),
-    m_dxfUnits( DXF_UNITS::INCHES ),
-    m_printMaskLayer()
+    m_dxfUnits( DXF_UNITS::INCHES )
 {
-}
\ No newline at end of file
+    m_plotDrawingSheet = false;
+
+    m_params.emplace_back(
+            new JOB_PARAM<wxString>( "drawing_sheet", &m_drawingSheet, m_drawingSheet ) );
+    m_params.emplace_back(
+            new JOB_PARAM<bool>( "plot_footprint_values", &m_plotFootprintValues, m_plotFootprintValues ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "plot_ref_des", &m_plotRefDes, m_plotRefDes ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "plot_graphic_items_using_contours", &m_plotGraphicItemsUsingContours,
+                                                m_plotGraphicItemsUsingContours ) );
+    m_params.emplace_back(
+            new JOB_PARAM<bool>( "use_drill_origin", &m_useDrillOrigin, m_useDrillOrigin ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "plot_border_title_blocks", &m_plotDrawingSheet,
+                                                m_plotDrawingSheet ) );
+    m_params.emplace_back( new JOB_PARAM<DXF_UNITS>( "units", &m_dxfUnits, m_dxfUnits ) );
+    m_params.emplace_back(
+            new JOB_PARAM<LSEQ>( "layers", &m_printMaskLayer, m_printMaskLayer ) );
+}
+
+
+wxString JOB_EXPORT_PCB_DXF::GetDescription()
+{
+    return wxString::Format( _( "PCB DXF export" ) );
+}
+
+REGISTER_JOB( pcb_export_dxf, _HKI( "PCB: Export DXF" ), KIWAY::FACE_PCB, JOB_EXPORT_PCB_DXF );
\ No newline at end of file
diff --git a/common/jobs/job_export_pcb_dxf.h b/common/jobs/job_export_pcb_dxf.h
index 621ff40b94..8d9314318e 100644
--- a/common/jobs/job_export_pcb_dxf.h
+++ b/common/jobs/job_export_pcb_dxf.h
@@ -25,12 +25,14 @@
 #include <layer_ids.h>
 #include <lseq.h>
 #include <wx/string.h>
+#include <jobs/job_export_pcb_plot.h>
 #include "job.h"
 
-class KICOMMON_API JOB_EXPORT_PCB_DXF : public JOB
+class KICOMMON_API JOB_EXPORT_PCB_DXF : public JOB_EXPORT_PCB_PLOT
 {
 public:
     JOB_EXPORT_PCB_DXF( bool aIsCli );
+    wxString GetDescription() override;
 
     enum class DXF_UNITS
     {
@@ -38,18 +40,9 @@ public:
         MILLIMETERS
     };
 
-    wxString m_filename;
-    wxString m_outputFile;
-    wxString m_drawingSheet;
-
-    bool m_plotFootprintValues;
-    bool m_plotRefDes;
     bool m_plotGraphicItemsUsingContours;
     bool m_useDrillOrigin;
-    bool m_plotBorderTitleBlocks;
     DXF_UNITS m_dxfUnits;
-
-    LSEQ m_printMaskLayer;
 };
 
 #endif
diff --git a/common/jobs/job_export_pcb_gencad.cpp b/common/jobs/job_export_pcb_gencad.cpp
index 01a065ece2..8c7e6627ab 100644
--- a/common/jobs/job_export_pcb_gencad.cpp
+++ b/common/jobs/job_export_pcb_gencad.cpp
@@ -22,7 +22,7 @@
 
 
 JOB_EXPORT_PCB_GENCAD::JOB_EXPORT_PCB_GENCAD( bool aIsCli ) :
-    JOB( "gencad", aIsCli ),
+    JOB( "gencad", false, aIsCli ),
     m_flipBottomPads( false ),
     m_useIndividualShapes( false ),
     m_storeOriginCoords( false ),
diff --git a/common/jobs/job_export_pcb_gencad.h b/common/jobs/job_export_pcb_gencad.h
index ec0f4e191e..b21558ead7 100644
--- a/common/jobs/job_export_pcb_gencad.h
+++ b/common/jobs/job_export_pcb_gencad.h
@@ -31,8 +31,6 @@ class KICOMMON_API JOB_EXPORT_PCB_GENCAD : public JOB
 {
 public:
     JOB_EXPORT_PCB_GENCAD( bool aIsCli );
-
-    wxString m_outputFile;
     wxString m_filename;
 
     bool m_flipBottomPads;
diff --git a/common/jobs/job_export_pcb_gerber.cpp b/common/jobs/job_export_pcb_gerber.cpp
index 732e1a7f3e..f02bcc06b7 100644
--- a/common/jobs/job_export_pcb_gerber.cpp
+++ b/common/jobs/job_export_pcb_gerber.cpp
@@ -19,29 +19,65 @@
  */
 
 #include <jobs/job_export_pcb_gerber.h>
+#include <jobs/job_registry.h>
+#include <i18n_utility.h>
 
 
 JOB_EXPORT_PCB_GERBER::JOB_EXPORT_PCB_GERBER( const std::string& aType, bool aIsCli ) :
-    JOB( aType, aIsCli ),
-    m_filename(),
-    m_outputFile(),
-    m_drawingSheet(),
-    m_plotFootprintValues( true ),
-    m_plotRefDes( true ),
-    m_plotBorderTitleBlocks( false ),
+    JOB_EXPORT_PCB_PLOT( JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::GERBER, aType, false, aIsCli ),
     m_subtractSolderMaskFromSilk( false ),
     m_includeNetlistAttributes( true ),
     m_useX2Format( true ),
     m_disableApertureMacros( false ),
     m_useAuxOrigin( false ),
     m_useProtelFileExtension( true ),
-    m_precision( 5 ),
-    m_printMaskLayer()
+    m_precision( 5 )
 {
+    m_plotDrawingSheet = false;
+
+    m_params.emplace_back( new JOB_PARAM<wxString>( "drawing_sheet",
+                                                    &m_drawingSheet,
+                                                    m_drawingSheet ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "plot_footprint_values",
+                                                &m_plotFootprintValues,
+                                                m_plotFootprintValues ) );
+
+    m_params.emplace_back( new JOB_PARAM<bool>( "plot_ref_des", &m_plotRefDes, m_plotRefDes ) );
+
+    m_params.emplace_back( new JOB_PARAM<bool>( "plot_drawing_sheet",
+                                                &m_plotDrawingSheet,
+                                                m_plotDrawingSheet ) );
+
+
+    m_params.emplace_back( new JOB_PARAM<bool>( "subtract_solder_mask_from_silk",
+                                                &m_subtractSolderMaskFromSilk,
+                                                m_subtractSolderMaskFromSilk ) );
+
+    m_params.emplace_back( new JOB_PARAM<bool>( "include_netlist_attributes",
+                                                &m_includeNetlistAttributes,
+                                                m_includeNetlistAttributes ) );
+
+    m_params.emplace_back( new JOB_PARAM<bool>( "use_x2_format", &m_useX2Format, m_useX2Format ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "disable_aperture_macros", &m_disableApertureMacros,
+                                                m_disableApertureMacros ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "use_aux_origin",
+                                                &m_useAuxOrigin,
+                                                m_useAuxOrigin ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "use_protel_file_extension",
+                                                &m_useProtelFileExtension,
+                                                m_useProtelFileExtension ) );
+    m_params.emplace_back( new JOB_PARAM<int>( "precision", &m_precision, m_precision ) );
+    m_params.emplace_back( new JOB_PARAM<LSEQ>( "layers", &m_printMaskLayer, m_printMaskLayer ) );
 }
 
 
 JOB_EXPORT_PCB_GERBER::JOB_EXPORT_PCB_GERBER( bool aIsCli ) :
     JOB_EXPORT_PCB_GERBER( "gerber", aIsCli )
 {
+}
+
+
+wxString JOB_EXPORT_PCB_GERBER::GetDescription()
+{
+    return wxString::Format( _( "Single gerber export" ) );
 }
\ No newline at end of file
diff --git a/common/jobs/job_export_pcb_gerber.h b/common/jobs/job_export_pcb_gerber.h
index 669f6583e3..37366b42ce 100644
--- a/common/jobs/job_export_pcb_gerber.h
+++ b/common/jobs/job_export_pcb_gerber.h
@@ -25,21 +25,15 @@
 #include <layer_ids.h>
 #include <lseq.h>
 #include <wx/string.h>
-#include "job.h"
+#include <jobs/job_export_pcb_plot.h>
 
-class KICOMMON_API JOB_EXPORT_PCB_GERBER : public JOB
+class KICOMMON_API JOB_EXPORT_PCB_GERBER : public JOB_EXPORT_PCB_PLOT
 {
 public:
     JOB_EXPORT_PCB_GERBER( const std::string& aType, bool aIsCli );
     JOB_EXPORT_PCB_GERBER( bool aIsCli );
+    wxString GetDescription() override;
 
-    wxString m_filename;
-    wxString m_outputFile;
-    wxString m_drawingSheet;
-
-    bool m_plotFootprintValues;
-    bool m_plotRefDes;
-    bool m_plotBorderTitleBlocks;
     bool m_subtractSolderMaskFromSilk;
     bool m_includeNetlistAttributes;
     bool m_useX2Format;
@@ -48,9 +42,6 @@ public:
     bool m_useProtelFileExtension;
 
     int m_precision;
-
-
-    LSEQ m_printMaskLayer;
 };
 
 #endif
diff --git a/common/jobs/job_export_pcb_gerbers.cpp b/common/jobs/job_export_pcb_gerbers.cpp
index 112b06877f..fd9dce9380 100644
--- a/common/jobs/job_export_pcb_gerbers.cpp
+++ b/common/jobs/job_export_pcb_gerbers.cpp
@@ -19,7 +19,9 @@
  */
 
 #include <jobs/job_export_pcb_gerbers.h>
-
+#include <jobs/lset_json.h>
+#include <jobs/job_registry.h>
+#include <i18n_utility.h>
 
 JOB_EXPORT_PCB_GERBERS::JOB_EXPORT_PCB_GERBERS( bool aIsCli ) :
         JOB_EXPORT_PCB_GERBER( "gerbers", aIsCli ),
@@ -27,4 +29,22 @@ JOB_EXPORT_PCB_GERBERS::JOB_EXPORT_PCB_GERBERS( bool aIsCli ) :
         m_layersIncludeOnAllSet( false ),
         m_useBoardPlotParams( false )
 {
-}
\ No newline at end of file
+    m_params.emplace_back( new JOB_PARAM<bool>( "use_board_plot_params", &m_useBoardPlotParams,
+                                                m_useBoardPlotParams ) );
+
+    m_params.emplace_back( new JOB_PARAM<bool>( "layers_include_on_all_set", &m_layersIncludeOnAllSet,
+                                                m_layersIncludeOnAllSet ) );
+
+    m_params.emplace_back( new JOB_PARAM<LSET>( "layers_include_on_all", &m_layersIncludeOnAll,
+                                                m_layersIncludeOnAll ) );
+}
+
+
+wxString JOB_EXPORT_PCB_GERBERS::GetDescription()
+{
+    return wxString::Format( _( "Multi gerber export" ) );
+}
+
+
+REGISTER_JOB( pcb_export_gerbers, _HKI( "PCB: Export Gerbers" ), KIWAY::FACE_PCB,
+              JOB_EXPORT_PCB_GERBERS );
\ No newline at end of file
diff --git a/common/jobs/job_export_pcb_gerbers.h b/common/jobs/job_export_pcb_gerbers.h
index 3312e1aa09..8f7eb00177 100644
--- a/common/jobs/job_export_pcb_gerbers.h
+++ b/common/jobs/job_export_pcb_gerbers.h
@@ -32,6 +32,7 @@ class KICOMMON_API JOB_EXPORT_PCB_GERBERS : public JOB_EXPORT_PCB_GERBER
 {
 public:
     JOB_EXPORT_PCB_GERBERS( bool aIsCli );
+    wxString GetDescription() override;
 
     LSET m_layersIncludeOnAll;
 
diff --git a/common/jobs/job_export_pcb_ipc2581.cpp b/common/jobs/job_export_pcb_ipc2581.cpp
index 943e737b72..e1b5509c84 100644
--- a/common/jobs/job_export_pcb_ipc2581.cpp
+++ b/common/jobs/job_export_pcb_ipc2581.cpp
@@ -19,11 +19,25 @@
  */
 
 #include <jobs/job_export_pcb_ipc2581.h>
+#include <jobs/job_registry.h>
+#include <i18n_utility.h>
+#include <wildcards_and_files_ext.h>
+
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_IPC2581::IPC2581_UNITS,
+                              {
+                                      { JOB_EXPORT_PCB_IPC2581::IPC2581_UNITS::INCHES, "in" },
+                                      { JOB_EXPORT_PCB_IPC2581::IPC2581_UNITS::MILLIMETERS, "mm" },
+                              } )
+
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_IPC2581::IPC2581_VERSION,
+                              {
+                                      { JOB_EXPORT_PCB_IPC2581::IPC2581_VERSION::B, "B" },
+                                      { JOB_EXPORT_PCB_IPC2581::IPC2581_VERSION::C, "C" },
+                              } )
 
 JOB_EXPORT_PCB_IPC2581::JOB_EXPORT_PCB_IPC2581( bool aIsCli ) :
-    JOB( "ipc2581", aIsCli ),
+    JOB( "ipc2581", false, aIsCli ),
     m_filename(),
-    m_outputFile(),
     m_drawingSheet(),
     m_units( IPC2581_UNITS::MILLIMETERS ),
     m_version( IPC2581_VERSION::C ),
@@ -35,4 +49,38 @@ JOB_EXPORT_PCB_IPC2581::JOB_EXPORT_PCB_IPC2581( bool aIsCli ) :
     m_colDistPn(),
     m_colDist()
 {
-}
\ No newline at end of file
+    m_params.emplace_back( new JOB_PARAM<wxString>( "drawing_sheet", &m_drawingSheet, m_drawingSheet ) );
+    m_params.emplace_back( new JOB_PARAM<IPC2581_UNITS>( "units", &m_units, m_units ) );
+    m_params.emplace_back( new JOB_PARAM<IPC2581_VERSION>( "version", &m_version, m_version ) );
+    m_params.emplace_back( new JOB_PARAM<int>( "precision", &m_precision, m_precision ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "compress", &m_compress, m_compress ) );
+    m_params.emplace_back( new JOB_PARAM<wxString>( "field_bom_map.internal_id",
+                                                    &m_colInternalId,
+                                                    m_colInternalId ) );
+    m_params.emplace_back( new JOB_PARAM<wxString>( "field_bom_map.mfg_pn",
+                                                    &m_colMfgPn, m_colMfgPn ) );
+    m_params.emplace_back( new JOB_PARAM<wxString>( "field_bom_map.mfg", &m_colMfg, m_colMfg ) );
+    m_params.emplace_back( new JOB_PARAM<wxString>( "field_bom_map.dist_pn",
+                                                    &m_colDistPn,
+                                                    m_colDistPn ) );
+    m_params.emplace_back( new JOB_PARAM<wxString>( "field_bom_map.dist", &m_colDist, m_colDist ) );
+}
+
+
+wxString JOB_EXPORT_PCB_IPC2581::GetDescription()
+{
+    return wxString::Format( _( "IPC2581 export" ) );
+}
+
+
+void JOB_EXPORT_PCB_IPC2581::SetDefaultOutputPath( const wxString& aReferenceName )
+{
+    wxFileName fn = aReferenceName;
+
+    fn.SetExt( FILEEXT::Ipc2581FileExtension );
+
+    SetOutputPath( fn.GetFullName() );
+}
+
+REGISTER_JOB( pcb_export_ipc2581, _HKI( "PCB: Export IPC2581" ), KIWAY::FACE_PCB,
+              JOB_EXPORT_PCB_IPC2581 );
\ No newline at end of file
diff --git a/common/jobs/job_export_pcb_ipc2581.h b/common/jobs/job_export_pcb_ipc2581.h
index 0454228461..b965185f2f 100644
--- a/common/jobs/job_export_pcb_ipc2581.h
+++ b/common/jobs/job_export_pcb_ipc2581.h
@@ -29,6 +29,9 @@ class KICOMMON_API JOB_EXPORT_PCB_IPC2581 : public JOB
 {
 public:
     JOB_EXPORT_PCB_IPC2581( bool aIsCli );
+    wxString GetDescription() override;
+
+    void SetDefaultOutputPath( const wxString& aReferenceName );
 
     enum class IPC2581_UNITS
     {
@@ -43,7 +46,6 @@ public:
     };
 
     wxString m_filename;
-    wxString m_outputFile;
     wxString m_drawingSheet;
 
     IPC2581_UNITS m_units;
diff --git a/common/jobs/job_export_pcb_pdf.cpp b/common/jobs/job_export_pcb_pdf.cpp
index d1b4e4c186..8e502095fb 100644
--- a/common/jobs/job_export_pcb_pdf.cpp
+++ b/common/jobs/job_export_pcb_pdf.cpp
@@ -19,25 +19,39 @@
  */
 
 #include <jobs/job_export_pcb_pdf.h>
+#include <jobs/job_registry.h>
+#include <i18n_utility.h>
 
 
 JOB_EXPORT_PCB_PDF::JOB_EXPORT_PCB_PDF( bool aIsCli ) :
-        JOB( "pdf", aIsCli ),
-        m_filename(),
-        m_outputFile(),
-        m_colorTheme(),
-        m_drawingSheet(),
-        m_mirror( false ),
-        m_blackAndWhite( false ),
-        m_negative( false ),
-        m_plotFootprintValues( true ),
-        m_plotRefDes( true ),
-        m_plotBorderTitleBlocks( false ),
-        m_printMaskLayer(),
-        m_sketchPadsOnFabLayers( false ),
-        m_hideDNPFPsOnFabLayers( false ),
-        m_sketchDNPFPsOnFabLayers( true ),
-        m_crossoutDNPFPsOnFabLayers( true ),
-        m_drillShapeOption( 2 )
+        JOB_EXPORT_PCB_PLOT( JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::PDF, "pdf", false, aIsCli )
 {
-}
\ No newline at end of file
+    m_plotDrawingSheet = false;
+
+    m_params.emplace_back( new JOB_PARAM<wxString>( "color_theme", &m_colorTheme, m_colorTheme ) );
+    m_params.emplace_back(
+            new JOB_PARAM<wxString>( "drawing_sheet", &m_drawingSheet, m_drawingSheet ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "mirror", &m_mirror, m_mirror ) );
+    m_params.emplace_back(
+            new JOB_PARAM<bool>( "black_and_white", &m_blackAndWhite, m_blackAndWhite ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "negative", &m_negative, m_negative ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "plot_footprint_values", &m_plotFootprintValues,
+                                                m_plotFootprintValues ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "plot_ref_des", &m_plotRefDes, m_plotRefDes ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "plot_border_title_blocks", &m_plotDrawingSheet,
+                                                m_plotDrawingSheet ) );
+    m_params.emplace_back( new JOB_PARAM<LSEQ>( "layers", &m_printMaskLayer, m_printMaskLayer ) );
+    m_params.emplace_back( new JOB_PARAM<bool>(
+            "sketch_pads_on_fab_layers", &m_sketchPadsOnFabLayers, m_sketchPadsOnFabLayers ) );
+    m_params.emplace_back(
+            new JOB_PARAM<int>( "drill_shape", &m_drillShapeOption, m_drillShapeOption ) );
+}
+
+
+wxString JOB_EXPORT_PCB_PDF::GetDescription()
+{
+    return wxString::Format( _( "PCB PDF export" ) );
+}
+
+
+REGISTER_JOB( pcb_export_pdf, _HKI( "PCB: Export PDF" ), KIWAY::FACE_PCB, JOB_EXPORT_PCB_PDF );
\ No newline at end of file
diff --git a/common/jobs/job_export_pcb_pdf.h b/common/jobs/job_export_pcb_pdf.h
index 2ded1bf74b..6b642c6271 100644
--- a/common/jobs/job_export_pcb_pdf.h
+++ b/common/jobs/job_export_pcb_pdf.h
@@ -26,35 +26,13 @@
 #include <layer_ids.h>
 #include <lseq.h>
 #include <wx/string.h>
-#include "job.h"
+#include <jobs/job_export_pcb_plot.h>
 
-class KICOMMON_API JOB_EXPORT_PCB_PDF : public JOB
+class KICOMMON_API JOB_EXPORT_PCB_PDF : public JOB_EXPORT_PCB_PLOT
 {
 public:
     JOB_EXPORT_PCB_PDF( bool aIsCli );
-
-    wxString m_filename;
-    wxString m_outputFile;
-    wxString m_colorTheme;
-    wxString m_drawingSheet;
-
-    bool m_mirror;
-    bool m_blackAndWhite;
-    bool m_negative;
-    bool m_plotFootprintValues;
-    bool m_plotRefDes;
-    bool m_plotBorderTitleBlocks;
-
-    LSEQ m_printMaskLayer;
-
-    bool m_sketchPadsOnFabLayers;
-    bool m_hideDNPFPsOnFabLayers;
-    bool m_sketchDNPFPsOnFabLayers;
-    bool m_crossoutDNPFPsOnFabLayers;
-
-    // How holes in pads/vias are plotted:
-    // 0 = no hole, 1 = small shape, 2 = actual shape
-    int m_drillShapeOption;
+    wxString GetDescription() override;
 };
 
 #endif
diff --git a/common/jobs/job_export_pcb_plot.cpp b/common/jobs/job_export_pcb_plot.cpp
new file mode 100644
index 0000000000..6dc647a304
--- /dev/null
+++ b/common/jobs/job_export_pcb_plot.cpp
@@ -0,0 +1,27 @@
+
+
+#include <jobs/job_export_pcb_plot.h>
+
+JOB_EXPORT_PCB_PLOT::JOB_EXPORT_PCB_PLOT( PLOT_FORMAT aFormat, const std::string& aType,
+                                          bool aOutputIsDirectory,
+                                          bool aIsCli )
+	: JOB( aType, aOutputIsDirectory, aIsCli ),
+    m_plotFormat( aFormat ),
+	m_filename(),
+	m_colorTheme(),
+	m_drawingSheet(),
+	m_mirror( false ),
+	m_blackAndWhite( false ),
+	m_negative( false ),
+	m_sketchPadsOnFabLayers( false ),
+	m_hideDNPFPsOnFabLayers( false ),
+	m_sketchDNPFPsOnFabLayers( true ),
+	m_crossoutDNPFPsOnFabLayers( true ),
+	m_plotFootprintValues( true ),
+	m_plotRefDes( true ),
+	m_plotDrawingSheet( true ),
+	m_printMaskLayer(),
+	m_drillShapeOption( 2 )
+{
+
+}
\ No newline at end of file
diff --git a/common/jobs/job_export_pcb_plot.h b/common/jobs/job_export_pcb_plot.h
new file mode 100644
index 0000000000..23aec50f68
--- /dev/null
+++ b/common/jobs/job_export_pcb_plot.h
@@ -0,0 +1,72 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 1992-2023 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <kicommon.h>
+#include <kicommon.h>
+#include <layer_ids.h>
+#include <lseq.h>
+#include <wx/string.h>
+#include "job.h"
+
+class KICOMMON_API JOB_EXPORT_PCB_PLOT : public JOB
+{
+public:
+    enum class PLOT_FORMAT
+    {
+        HPGL,
+        GERBER,
+        POST,
+        DXF,
+        PDF,
+        SVG
+    };
+
+    JOB_EXPORT_PCB_PLOT( PLOT_FORMAT aFormat, const std::string& aType, bool aOutputIsDirectory, bool aIsCli );
+
+    PLOT_FORMAT m_plotFormat;
+
+    wxString m_filename;
+    wxString m_colorTheme;
+    wxString m_drawingSheet;
+
+    /**
+     * Common Options
+     */
+    bool m_mirror;
+    bool m_blackAndWhite;
+    bool m_negative;
+
+    bool m_sketchPadsOnFabLayers;
+    bool m_hideDNPFPsOnFabLayers;
+    bool m_sketchDNPFPsOnFabLayers;
+    bool m_crossoutDNPFPsOnFabLayers;
+
+    bool m_plotFootprintValues;
+    bool m_plotRefDes;
+    bool m_plotDrawingSheet;
+
+    LSEQ m_printMaskLayer;
+
+    // How holes in pads/vias are plotted:
+    // 0 = no hole, 1 = small shape, 2 = actual shape
+    int m_drillShapeOption;
+};
diff --git a/common/jobs/job_export_pcb_pos.cpp b/common/jobs/job_export_pcb_pos.cpp
index 2cf82cddfa..74fd4a416f 100644
--- a/common/jobs/job_export_pcb_pos.cpp
+++ b/common/jobs/job_export_pcb_pos.cpp
@@ -19,20 +19,91 @@
  */
 
 #include <jobs/job_export_pcb_pos.h>
+#include <jobs/job_registry.h>
+#include <i18n_utility.h>
+#include <wildcards_and_files_ext.h>
 
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_POS::FORMAT,
+                              {
+                                      { JOB_EXPORT_PCB_POS::FORMAT::ASCII, "ascii" },
+                                      { JOB_EXPORT_PCB_POS::FORMAT::CSV, "csv" },
+                                      { JOB_EXPORT_PCB_POS::FORMAT::GERBER, "gerber" },
+                              } )
+
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_POS::SIDE,
+                              {
+                                      { JOB_EXPORT_PCB_POS::SIDE::FRONT, "front" },
+                                      { JOB_EXPORT_PCB_POS::SIDE::BACK, "back" },
+                                      { JOB_EXPORT_PCB_POS::SIDE::BOTH, "both" },
+                              } )
+
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_PCB_POS::UNITS,
+                              {
+                                      { JOB_EXPORT_PCB_POS::UNITS::INCHES, "in" },
+                                      { JOB_EXPORT_PCB_POS::UNITS::MILLIMETERS, "mm" },
+                              } )
 
 JOB_EXPORT_PCB_POS::JOB_EXPORT_PCB_POS( bool aIsCli ) :
-    JOB( "pos", aIsCli ),
+    JOB( "pos", false, aIsCli ),
     m_filename(),
-    m_outputFile(),
     m_useDrillPlaceFileOrigin( true ),
     m_smdOnly( false ),
     m_excludeFootprintsWithTh( false ),
     m_excludeDNP( false ),
-    m_negateBottomX( false )
+    m_negateBottomX( false ),
+    m_side( SIDE::BOTH ),
+    m_units( UNITS::MILLIMETERS ),
+    m_format( FORMAT::ASCII ),
+    m_gerberBoardEdge( true )
 {
-    m_side = SIDE::BOTH;
-    m_units = UNITS::MILLIMETERS;
-    m_format = FORMAT::ASCII;
-    m_gerberBoardEdge = true;
-}
\ No newline at end of file
+    m_params.emplace_back( new JOB_PARAM<bool>( "use_drill_place_file_origin",
+                                                &m_useDrillPlaceFileOrigin,
+                                                m_useDrillPlaceFileOrigin ) );
+
+    m_params.emplace_back( new JOB_PARAM<bool>( "smd_only",
+                                                &m_smdOnly,
+                                                m_smdOnly ) );
+
+    m_params.emplace_back( new JOB_PARAM<bool>( "exclude_footprints_with_th",
+                                                &m_excludeFootprintsWithTh,
+                                                m_excludeFootprintsWithTh ) );
+
+    m_params.emplace_back( new JOB_PARAM<bool>( "exclude_dnp",
+                                                &m_excludeDNP,
+                                                m_excludeDNP ) );
+
+    m_params.emplace_back( new JOB_PARAM<bool>( "negate_bottom_x",
+                                                &m_negateBottomX,
+                                                m_negateBottomX ) );
+
+    m_params.emplace_back( new JOB_PARAM<bool>( "gerber_board_edge",
+                                                &m_gerberBoardEdge,
+                                                m_gerberBoardEdge ) );
+
+    m_params.emplace_back( new JOB_PARAM<SIDE>( "side", &m_side, m_side ) );
+    m_params.emplace_back( new JOB_PARAM<UNITS>( "units", &m_units, m_units ) );
+    m_params.emplace_back( new JOB_PARAM<FORMAT>( "format", &m_format, m_format ) );
+}
+
+
+wxString JOB_EXPORT_PCB_POS::GetDescription()
+{
+    return wxString::Format( _( "Placement data export" ) );
+}
+
+
+void JOB_EXPORT_PCB_POS::SetDefaultOutputPath( const wxString& aReferenceName )
+{
+    wxFileName fn = aReferenceName;
+
+    if( m_format == JOB_EXPORT_PCB_POS::FORMAT::ASCII )
+        fn.SetExt( FILEEXT::FootprintPlaceFileExtension );
+    else if( m_format == JOB_EXPORT_PCB_POS::FORMAT::CSV )
+        fn.SetExt( FILEEXT::CsvFileExtension );
+    else if( m_format == JOB_EXPORT_PCB_POS::FORMAT::GERBER )
+        fn.SetExt( FILEEXT::GerberFileExtension );
+
+    SetOutputPath( 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/common/jobs/job_export_pcb_pos.h b/common/jobs/job_export_pcb_pos.h
index fe45a966ff..58ab0f34cb 100644
--- a/common/jobs/job_export_pcb_pos.h
+++ b/common/jobs/job_export_pcb_pos.h
@@ -30,9 +30,11 @@ class KICOMMON_API JOB_EXPORT_PCB_POS : public JOB
 {
 public:
     JOB_EXPORT_PCB_POS( bool aIsCli );
+    wxString GetDescription() override;
+
+    void SetDefaultOutputPath( const wxString& aReferenceName );
 
     wxString m_filename;
-    wxString m_outputFile;
 
     bool m_useDrillPlaceFileOrigin;
     bool m_smdOnly;
diff --git a/common/jobs/job_export_pcb_svg.cpp b/common/jobs/job_export_pcb_svg.cpp
index 843b32e1dd..9ccce1fc5d 100644
--- a/common/jobs/job_export_pcb_svg.cpp
+++ b/common/jobs/job_export_pcb_svg.cpp
@@ -19,24 +19,39 @@
  */
 
 #include <jobs/job_export_pcb_svg.h>
+#include <jobs/job_registry.h>
+#include <i18n_utility.h>
 
 
 JOB_EXPORT_PCB_SVG::JOB_EXPORT_PCB_SVG( bool aIsCli ) :
-    JOB( "svg", aIsCli ),
-    m_filename(),
-    m_outputFile(),
-    m_colorTheme(),
-    m_drawingSheet(),
-    m_mirror( false ),
-    m_blackAndWhite( false ),
-    m_negative( false ),
-    m_plotDrawingSheet( true ),
-    m_pageSizeMode( 0 ),
-    m_printMaskLayer(),
-    m_sketchPadsOnFabLayers( false ),
-    m_hideDNPFPsOnFabLayers( false ),
-    m_sketchDNPFPsOnFabLayers( true ),
-    m_crossoutDNPFPsOnFabLayers( true ),
-    m_drillShapeOption( 2 )
+    JOB_EXPORT_PCB_PLOT( JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::SVG, "svg", false, aIsCli ),
+    m_pageSizeMode( 0 )
 {
-}
\ No newline at end of file
+    m_plotDrawingSheet = true;
+
+    m_params.emplace_back( new JOB_PARAM<wxString>( "color_theme", &m_colorTheme, m_colorTheme ) );
+    m_params.emplace_back(
+            new JOB_PARAM<wxString>( "drawing_sheet", &m_drawingSheet, m_drawingSheet ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "mirror", &m_mirror, m_mirror ) );
+    m_params.emplace_back(
+            new JOB_PARAM<bool>( "black_and_white", &m_blackAndWhite, m_blackAndWhite ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "negative", &m_negative, m_negative ) );
+    m_params.emplace_back(
+            new JOB_PARAM<bool>( "plot_drawing_sheet", &m_plotDrawingSheet, m_plotDrawingSheet ) );
+    m_params.emplace_back( new JOB_PARAM<LSEQ>( "layers", &m_printMaskLayer, m_printMaskLayer ) );
+    m_params.emplace_back( new JOB_PARAM<bool>(
+            "sketch_pads_on_fab_layers", &m_sketchPadsOnFabLayers, m_sketchPadsOnFabLayers ) );
+    m_params.emplace_back(
+            new JOB_PARAM<int>( "page_size_mode", &m_pageSizeMode, m_pageSizeMode ) );
+    m_params.emplace_back(
+            new JOB_PARAM<int>( "drill_shape_option", &m_drillShapeOption, m_drillShapeOption ) );
+}
+
+
+wxString JOB_EXPORT_PCB_SVG::GetDescription()
+{
+    return wxString::Format( _( "PCB SVG export" ) );
+}
+
+
+REGISTER_JOB( pcb_export_svg, _HKI( "PCB: Export SVG" ), KIWAY::FACE_PCB, JOB_EXPORT_PCB_SVG );
\ No newline at end of file
diff --git a/common/jobs/job_export_pcb_svg.h b/common/jobs/job_export_pcb_svg.h
index c39c6db540..654cecc89c 100644
--- a/common/jobs/job_export_pcb_svg.h
+++ b/common/jobs/job_export_pcb_svg.h
@@ -25,34 +25,16 @@
 #include <layer_ids.h>
 #include <lseq.h>
 #include <wx/string.h>
+#include <jobs/job_export_pcb_plot.h>
 #include "job.h"
 
-class KICOMMON_API JOB_EXPORT_PCB_SVG : public JOB
+class KICOMMON_API JOB_EXPORT_PCB_SVG : public JOB_EXPORT_PCB_PLOT
 {
 public:
     JOB_EXPORT_PCB_SVG( bool aIsCli );
+    wxString GetDescription() override;
 
-    wxString m_filename;
-    wxString m_outputFile;
-    wxString m_colorTheme;
-    wxString m_drawingSheet;
-
-    bool m_mirror;
-    bool m_blackAndWhite;
-    bool m_negative;
-
-    bool m_plotDrawingSheet;
     int m_pageSizeMode;
-
-    LSEQ m_printMaskLayer;
-    bool m_sketchPadsOnFabLayers;
-    bool m_hideDNPFPsOnFabLayers;
-    bool m_sketchDNPFPsOnFabLayers;
-    bool m_crossoutDNPFPsOnFabLayers;
-
-    // How holes in pads/vias are plotted:
-    // 0 = no hole, 1 = small shape, 2 = actual shape
-    int m_drillShapeOption;
 };
 
 #endif
\ No newline at end of file
diff --git a/common/jobs/job_export_sch_bom.cpp b/common/jobs/job_export_sch_bom.cpp
index 5ea88dfa08..1f72b1c3c4 100644
--- a/common/jobs/job_export_sch_bom.cpp
+++ b/common/jobs/job_export_sch_bom.cpp
@@ -19,12 +19,13 @@
  */
 
 #include <jobs/job_export_sch_bom.h>
+#include <jobs/job_registry.h>
+#include <i18n_utility.h>
 
 
 JOB_EXPORT_SCH_BOM::JOB_EXPORT_SCH_BOM( bool aIsCli ) :
-    JOB( "bom", aIsCli ),
+    JOB( "bom", false, aIsCli ),
     m_filename(),
-    m_outputFile(),
 
     m_fieldDelimiter(),
     m_stringDelimiter(),
@@ -42,4 +43,47 @@ JOB_EXPORT_SCH_BOM::JOB_EXPORT_SCH_BOM( bool aIsCli ) :
     m_excludeDNP( false ),
     m_includeExcludedFromBOM( false )
 {
+    m_params.emplace_back( new JOB_PARAM<wxString>( "field_delimiter",
+                                                    &m_fieldDelimiter,
+                                                    m_fieldDelimiter ) );
+    m_params.emplace_back( new JOB_PARAM<wxString>( "string_delimiter",
+                                                    &m_stringDelimiter,
+                                                    m_stringDelimiter ) );
+    m_params.emplace_back( new JOB_PARAM<wxString>( "ref_delimiter",
+                                                    &m_refDelimiter,
+                                                    m_refDelimiter ) );
+    m_params.emplace_back( new JOB_PARAM<wxString>( "ref_range_delimiter",
+                                                    &m_refRangeDelimiter,
+                                                    m_refRangeDelimiter ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "keep_tabs", &m_keepTabs, m_keepTabs ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "keep_line_breaks",
+                                                &m_keepLineBreaks,
+                                                m_keepLineBreaks ) );
+    m_params.emplace_back( new JOB_PARAM<std::vector<wxString>>( "fields_ordered",
+                                                                 &m_fieldsOrdered,
+                                                                 m_fieldsOrdered ) );
+    m_params.emplace_back( new JOB_PARAM<std::vector<wxString>>( "fields_labels",
+                                                                 &m_fieldsLabels,
+                                                                 m_fieldsLabels ) );
+    m_params.emplace_back( new JOB_PARAM<std::vector<wxString>>( "fields_group_by",
+                                                                 &m_fieldsGroupBy,
+                                                                 m_fieldsGroupBy ) );
+    m_params.emplace_back( new JOB_PARAM<wxString>( "sort_field", &m_sortField, m_sortField ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "sort_asc", &m_sortAsc, m_sortAsc ) );
+    m_params.emplace_back( new JOB_PARAM<wxString>( "filter_string",
+                                                    &m_filterString,
+                                                    m_filterString ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "exclude_dnp", &m_excludeDNP, m_excludeDNP ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "include_excluded_from_bom",
+                                                &m_includeExcludedFromBOM,
+                                                m_includeExcludedFromBOM ) );
+
 }
+
+
+wxString JOB_EXPORT_SCH_BOM::GetDescription()
+{
+    return wxString::Format( _( "Schematic BOM export" ) );
+}
+
+REGISTER_JOB( sch_export_bom, _HKI( "Schematic: Export BOM" ), KIWAY::FACE_SCH, JOB_EXPORT_SCH_BOM );
\ No newline at end of file
diff --git a/common/jobs/job_export_sch_bom.h b/common/jobs/job_export_sch_bom.h
index 58a890f385..97d668680d 100644
--- a/common/jobs/job_export_sch_bom.h
+++ b/common/jobs/job_export_sch_bom.h
@@ -30,10 +30,10 @@ class KICOMMON_API JOB_EXPORT_SCH_BOM : public JOB
 {
 public:
     JOB_EXPORT_SCH_BOM( bool aIsCli );
+    wxString GetDescription() override;
 
     // Basic options
     wxString m_filename;
-    wxString m_outputFile;
 
     // Preset options (from schematic)
     wxString m_bomPresetName;
diff --git a/common/jobs/job_export_sch_netlist.cpp b/common/jobs/job_export_sch_netlist.cpp
index 16024b2535..694f6818d7 100644
--- a/common/jobs/job_export_sch_netlist.cpp
+++ b/common/jobs/job_export_sch_netlist.cpp
@@ -19,12 +19,48 @@
  */
 
 #include <jobs/job_export_sch_netlist.h>
+#include <jobs/job_registry.h>
+#include <i18n_utility.h>
 
 
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_EXPORT_SCH_NETLIST::FORMAT,
+                              {
+                                      { JOB_EXPORT_SCH_NETLIST::FORMAT::KICADSEXPR, "kicad" },
+                                      { JOB_EXPORT_SCH_NETLIST::FORMAT::KICADXML, "xml" },
+                                      { JOB_EXPORT_SCH_NETLIST::FORMAT::ALLEGRO, "allegro" },
+                                      { JOB_EXPORT_SCH_NETLIST::FORMAT::PADS, "pads" },
+                                      { JOB_EXPORT_SCH_NETLIST::FORMAT::CADSTAR, "cadstar" },
+                                      { JOB_EXPORT_SCH_NETLIST::FORMAT::ORCADPCB2, "orcadpcb2" },
+                                      { JOB_EXPORT_SCH_NETLIST::FORMAT::SPICE, "spice" },
+                                      { JOB_EXPORT_SCH_NETLIST::FORMAT::SPICEMODEL, "spicemodel" },
+                              } )
+
 JOB_EXPORT_SCH_NETLIST::JOB_EXPORT_SCH_NETLIST( bool aIsCli ) :
-    JOB( "netlist", aIsCli ),
+    JOB( "netlist", false, aIsCli ),
     m_filename(),
-    m_outputFile()
+    format( FORMAT::KICADSEXPR ),
+    m_spiceSaveAllVoltages( false ),
+    m_spiceSaveAllCurrents( false ),
+    m_spiceSaveAllDissipations( false ),
+    m_spiceSaveAllEvents( false )
 {
-    format = FORMAT::KICADSEXPR;
-}
\ No newline at end of file
+    m_params.emplace_back( new JOB_PARAM<FORMAT>( "format", &format, format ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "spice.save_all_voltages", &m_spiceSaveAllVoltages,
+                                                m_spiceSaveAllVoltages ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "spice.save_all_currents", &m_spiceSaveAllCurrents,
+                                                m_spiceSaveAllCurrents ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "spice.save_all_events", &m_spiceSaveAllEvents,
+                                                m_spiceSaveAllEvents ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "spice.save_all_dissipations", &m_spiceSaveAllDissipations,
+                                                m_spiceSaveAllDissipations ) );
+}
+
+
+wxString JOB_EXPORT_SCH_NETLIST::GetDescription()
+{
+    return wxString::Format( _( "Schematic Netlist Export" ) );
+}
+
+
+REGISTER_JOB( sch_export_netlist, _HKI( "Schematic: Export Netlist" ), KIWAY::FACE_SCH,
+              JOB_EXPORT_SCH_NETLIST );
\ No newline at end of file
diff --git a/common/jobs/job_export_sch_netlist.h b/common/jobs/job_export_sch_netlist.h
index fae5d3ed08..d0717811cd 100644
--- a/common/jobs/job_export_sch_netlist.h
+++ b/common/jobs/job_export_sch_netlist.h
@@ -29,9 +29,9 @@ class KICOMMON_API JOB_EXPORT_SCH_NETLIST : public JOB
 {
 public:
     JOB_EXPORT_SCH_NETLIST( bool aIsCli );
+    wxString GetDescription() override;
 
     wxString m_filename;
-    wxString m_outputFile;
 
     enum class FORMAT
     {
@@ -46,6 +46,11 @@ public:
     };
 
     FORMAT format;
+
+    bool m_spiceSaveAllVoltages;
+    bool m_spiceSaveAllCurrents;
+    bool m_spiceSaveAllDissipations;
+    bool m_spiceSaveAllEvents;
 };
 
 #endif
\ No newline at end of file
diff --git a/common/jobs/job_export_sch_plot.cpp b/common/jobs/job_export_sch_plot.cpp
index e7d266b16b..2c3253d82e 100644
--- a/common/jobs/job_export_sch_plot.cpp
+++ b/common/jobs/job_export_sch_plot.cpp
@@ -19,12 +19,54 @@
  */
 
 #include <jobs/job_export_sch_plot.h>
+#include <jobs/job_registry.h>
+#include <i18n_utility.h>
 
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_PAGE_SIZE,
+                              {
+                                      { JOB_PAGE_SIZE::PAGE_SIZE_AUTO, "auto" },
+                                      { JOB_PAGE_SIZE::PAGE_SIZE_A4, "A4" },
+                                      { JOB_PAGE_SIZE::PAGE_SIZE_A, "A" },
+                              } )
 
-JOB_EXPORT_SCH_PLOT::JOB_EXPORT_SCH_PLOT( bool aIsCli, SCH_PLOT_FORMAT aPlotFormat, wxString aFilename ) :
-        JOB( "plot", aIsCli ),
-        m_plotFormat( aPlotFormat ),
-        m_filename( aFilename ),
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_HPGL_PAGE_SIZE,
+                              {
+                                      { JOB_HPGL_PAGE_SIZE::DEFAULT, "default" },
+                                      { JOB_HPGL_PAGE_SIZE::SIZE_A5, "A5" },
+                                      { JOB_HPGL_PAGE_SIZE::SIZE_A4, "A4" },
+                                      { JOB_HPGL_PAGE_SIZE::SIZE_A3, "A3" },
+                                      { JOB_HPGL_PAGE_SIZE::SIZE_A2, "A2" },
+                                      { JOB_HPGL_PAGE_SIZE::SIZE_A1, "A1" },
+                                      { JOB_HPGL_PAGE_SIZE::SIZE_A0, "A0" },
+                                      { JOB_HPGL_PAGE_SIZE::SIZE_A, "A" },
+                                      { JOB_HPGL_PAGE_SIZE::SIZE_B, "B" },
+                                      { JOB_HPGL_PAGE_SIZE::SIZE_C, "C" },
+                                      { JOB_HPGL_PAGE_SIZE::SIZE_D, "D" },
+                                      { JOB_HPGL_PAGE_SIZE::SIZE_E, "E" },
+                              } )
+
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_HPGL_PLOT_ORIGIN_AND_UNITS,
+                              {
+                                      { JOB_HPGL_PLOT_ORIGIN_AND_UNITS::PLOTTER_BOT_LEFT, "default" },
+                                      { JOB_HPGL_PLOT_ORIGIN_AND_UNITS::PLOTTER_CENTER, "A5" },
+                                      { JOB_HPGL_PLOT_ORIGIN_AND_UNITS::USER_FIT_PAGE, "A4" },
+                                      { JOB_HPGL_PLOT_ORIGIN_AND_UNITS::USER_FIT_CONTENT, "A3" },
+                              } )
+
+NLOHMANN_JSON_SERIALIZE_ENUM( SCH_PLOT_FORMAT,
+                              {
+                                      { SCH_PLOT_FORMAT::HPGL, "hpgl" },
+                                      { SCH_PLOT_FORMAT::PDF, "pdf" },
+                                      { SCH_PLOT_FORMAT::GERBER, "gerber" },
+                                      { SCH_PLOT_FORMAT::POST, "post" },
+                                      { SCH_PLOT_FORMAT::SVG, "svg" },
+                                      { SCH_PLOT_FORMAT::DXF, "dxf" },
+                              } )
+
+JOB_EXPORT_SCH_PLOT::JOB_EXPORT_SCH_PLOT( bool aIsCli ) :
+        JOB( "plot", false, aIsCli ),
+        m_plotFormat( SCH_PLOT_FORMAT::PDF ),
+        m_filename(),
         m_drawingSheet(),
         m_plotAll( true ),
         m_plotDrawingSheet( true ),
@@ -40,4 +82,85 @@ JOB_EXPORT_SCH_PLOT::JOB_EXPORT_SCH_PLOT( bool aIsCli, SCH_PLOT_FORMAT aPlotForm
         m_outputFile(),
         m_HPGLPlotOrigin( JOB_HPGL_PLOT_ORIGIN_AND_UNITS::USER_FIT_CONTENT )
 {
-}
\ No newline at end of file
+    m_params.emplace_back(
+            new JOB_PARAM<SCH_PLOT_FORMAT>( "format", &m_plotFormat, m_plotFormat ) );
+    m_params.emplace_back(
+            new JOB_PARAM<wxString>( "drawing_sheet", &m_drawingSheet, m_drawingSheet ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "plot_all", &m_plotAll, m_plotAll ) );
+    m_params.emplace_back(
+            new JOB_PARAM<bool>( "plot_drawing_sheet", &m_plotDrawingSheet, m_plotDrawingSheet ) );
+    m_params.emplace_back(
+            new JOB_PARAM<bool>( "black_and_white", &m_blackAndWhite, m_blackAndWhite ) );
+    m_params.emplace_back(
+            new JOB_PARAM<JOB_PAGE_SIZE>( "page_size", &m_pageSizeSelect, m_pageSizeSelect ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "use_background_color", &m_useBackgroundColor,
+                                                m_useBackgroundColor ) );
+    m_params.emplace_back(
+            new JOB_PARAM<double>( "hpgl_pen_size", &m_HPGLPenSize, m_HPGLPenSize ) );
+    m_params.emplace_back( new JOB_PARAM<JOB_HPGL_PAGE_SIZE>(
+            "hpgl_page_size", &m_HPGLPaperSizeSelect, m_HPGLPaperSizeSelect ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "pdf_property_popups", &m_PDFPropertyPopups,
+                                                m_PDFPropertyPopups ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "pdf_metadata", &m_PDFMetadata, m_PDFMetadata ) );
+    m_params.emplace_back( new JOB_PARAM<wxString>( "color_theme", &m_theme, m_theme ) );
+    m_params.emplace_back(
+            new JOB_PARAM<wxString>( "output_filename", &m_outputFile, m_outputFile ) );
+    m_params.emplace_back(
+            new JOB_PARAM<wxString>( "output_directory", &m_outputDirectory, m_outputDirectory ) );
+    m_params.emplace_back( new JOB_PARAM<JOB_HPGL_PLOT_ORIGIN_AND_UNITS>(
+            "hpgl_plot_origin", &m_HPGLPlotOrigin, m_HPGLPlotOrigin ) );
+
+}
+
+
+wxString JOB_EXPORT_SCH_PLOT::GetDescription()
+{
+    return wxString::Format( _( "Schematic plot export" ) );
+}
+
+
+JOB_EXPORT_SCH_PLOT_PDF::JOB_EXPORT_SCH_PLOT_PDF( bool aIsCli ) :
+		JOB_EXPORT_SCH_PLOT( aIsCli )
+{
+    m_plotFormat = SCH_PLOT_FORMAT::PDF;
+}
+
+
+JOB_EXPORT_SCH_PLOT_DXF ::JOB_EXPORT_SCH_PLOT_DXF ( bool aIsCli ) :
+		JOB_EXPORT_SCH_PLOT( aIsCli )
+{
+	m_plotFormat = SCH_PLOT_FORMAT::DXF;
+}
+
+
+JOB_EXPORT_SCH_PLOT_SVG::JOB_EXPORT_SCH_PLOT_SVG( bool aIsCli ) :
+		JOB_EXPORT_SCH_PLOT( aIsCli )
+{
+	m_plotFormat = SCH_PLOT_FORMAT::SVG;
+}
+
+
+JOB_EXPORT_SCH_PLOT_PS::JOB_EXPORT_SCH_PLOT_PS( bool aIsCli ) :
+		JOB_EXPORT_SCH_PLOT( aIsCli )
+{
+	m_plotFormat = SCH_PLOT_FORMAT::POST;
+}
+
+
+JOB_EXPORT_SCH_PLOT_HPGL::JOB_EXPORT_SCH_PLOT_HPGL( bool aIsCli ) :
+		JOB_EXPORT_SCH_PLOT( aIsCli )
+{
+	m_plotFormat = SCH_PLOT_FORMAT::HPGL;
+}
+
+
+REGISTER_JOB( sch_export_plot_svg, _HKI( "Schematic: Export SVG" ), KIWAY::FACE_SCH,
+              JOB_EXPORT_SCH_PLOT_SVG );
+REGISTER_JOB( sch_export_plot_hpgl, _HKI( "Schematic: Export HPGL" ), KIWAY::FACE_SCH,
+              JOB_EXPORT_SCH_PLOT_HPGL );
+REGISTER_JOB( sch_export_plot_ps, _HKI( "Schematic: Export PS" ), KIWAY::FACE_SCH,
+              JOB_EXPORT_SCH_PLOT_PS );
+REGISTER_JOB( sch_export_plot_dxf, _HKI( "Schematic: Export DXF" ), KIWAY::FACE_SCH,
+              JOB_EXPORT_SCH_PLOT_DXF );
+REGISTER_JOB( sch_export_plot_pdf, _HKI( "Schematic: Export PDF" ), KIWAY::FACE_SCH,
+              JOB_EXPORT_SCH_PLOT_PDF );
\ No newline at end of file
diff --git a/common/jobs/job_export_sch_plot.h b/common/jobs/job_export_sch_plot.h
index 3cec6001c1..67c491c792 100644
--- a/common/jobs/job_export_sch_plot.h
+++ b/common/jobs/job_export_sch_plot.h
@@ -75,7 +75,8 @@ enum class SCH_PLOT_FORMAT
 class KICOMMON_API JOB_EXPORT_SCH_PLOT : public JOB
 {
 public:
-    JOB_EXPORT_SCH_PLOT( bool aIsCli, SCH_PLOT_FORMAT aPlotFormat, wxString aFilename );
+    JOB_EXPORT_SCH_PLOT( bool aIsCli );
+    wxString GetDescription() override;
 
     SCH_PLOT_FORMAT       m_plotFormat;
     wxString              m_filename;
@@ -100,4 +101,39 @@ public:
     JOB_HPGL_PLOT_ORIGIN_AND_UNITS m_HPGLPlotOrigin;
 };
 
+
+class KICOMMON_API JOB_EXPORT_SCH_PLOT_PDF : public JOB_EXPORT_SCH_PLOT
+{
+public:
+    JOB_EXPORT_SCH_PLOT_PDF( bool aIsCli );
+};
+
+
+class KICOMMON_API JOB_EXPORT_SCH_PLOT_DXF : public JOB_EXPORT_SCH_PLOT
+{
+public:
+    JOB_EXPORT_SCH_PLOT_DXF( bool aIsCli );
+};
+
+
+class KICOMMON_API JOB_EXPORT_SCH_PLOT_SVG : public JOB_EXPORT_SCH_PLOT
+{
+public:
+    JOB_EXPORT_SCH_PLOT_SVG( bool aIsCli );
+};
+
+
+class KICOMMON_API JOB_EXPORT_SCH_PLOT_PS : public JOB_EXPORT_SCH_PLOT
+{
+public:
+    JOB_EXPORT_SCH_PLOT_PS( bool aIsCli );
+};
+
+
+class KICOMMON_API JOB_EXPORT_SCH_PLOT_HPGL : public JOB_EXPORT_SCH_PLOT
+{
+public:
+    JOB_EXPORT_SCH_PLOT_HPGL( bool aIsCli );
+};
+
 #endif
\ No newline at end of file
diff --git a/common/jobs/job_export_sch_pythonbom.cpp b/common/jobs/job_export_sch_pythonbom.cpp
index d98908cc96..c159282e9a 100644
--- a/common/jobs/job_export_sch_pythonbom.cpp
+++ b/common/jobs/job_export_sch_pythonbom.cpp
@@ -19,11 +19,22 @@
  */
 
 #include <jobs/job_export_sch_pythonbom.h>
+#include <jobs/job_registry.h>
+#include <i18n_utility.h>
 
 
 JOB_EXPORT_SCH_PYTHONBOM::JOB_EXPORT_SCH_PYTHONBOM( bool aIsCli ) :
-        JOB( "pythonbom", aIsCli ),
-        m_filename(),
-        m_outputFile()
+        JOB( "pythonbom", false, aIsCli ),
+        m_filename()
 {
-}
\ No newline at end of file
+}
+
+
+wxString JOB_EXPORT_SCH_PYTHONBOM::GetDescription()
+{
+    return wxString::Format( _( "Schematic PythonBOM export" ) );
+}
+
+
+REGISTER_JOB( sch_export_pythonbom, _HKI( "Schematic: Export PythonBOM" ), KIWAY::FACE_SCH,
+              JOB_EXPORT_SCH_PYTHONBOM );
\ No newline at end of file
diff --git a/common/jobs/job_export_sch_pythonbom.h b/common/jobs/job_export_sch_pythonbom.h
index 888836766a..60a79aee1b 100644
--- a/common/jobs/job_export_sch_pythonbom.h
+++ b/common/jobs/job_export_sch_pythonbom.h
@@ -29,9 +29,9 @@ class KICOMMON_API JOB_EXPORT_SCH_PYTHONBOM : public JOB
 {
 public:
     JOB_EXPORT_SCH_PYTHONBOM( bool aIsCli );
+    wxString GetDescription() override;
 
     wxString m_filename;
-    wxString m_outputFile;
 };
 
 #endif
\ No newline at end of file
diff --git a/common/jobs/job_fp_export_svg.cpp b/common/jobs/job_fp_export_svg.cpp
index ed15af6347..1bc54c56e2 100644
--- a/common/jobs/job_fp_export_svg.cpp
+++ b/common/jobs/job_fp_export_svg.cpp
@@ -22,10 +22,9 @@
 
 
 JOB_FP_EXPORT_SVG::JOB_FP_EXPORT_SVG( bool aIsCli ) :
-    JOB( "fpsvg", aIsCli ),
+    JOB( "fpsvg", true, aIsCli ),
     m_libraryPath(),
     m_footprint(),
-    m_outputDirectory(),
     m_blackAndWhite( false ),
     m_sketchPadsOnFabLayers( false ),
     m_hideDNPFPsOnFabLayers( false ),
diff --git a/common/jobs/job_fp_upgrade.cpp b/common/jobs/job_fp_upgrade.cpp
index 10cfbc4ee0..621dee3525 100644
--- a/common/jobs/job_fp_upgrade.cpp
+++ b/common/jobs/job_fp_upgrade.cpp
@@ -22,9 +22,8 @@
 
 
 JOB_FP_UPGRADE::JOB_FP_UPGRADE( bool aIsCli ) :
-        JOB( "fpupgrade", aIsCli ),
+        JOB( "fpupgrade", true, aIsCli ),
         m_libraryPath(),
-        m_outputLibraryPath(),
         m_force( false )
 {
 }
\ No newline at end of file
diff --git a/common/jobs/job_pcb_drc.cpp b/common/jobs/job_pcb_drc.cpp
index 5c54c14810..b6c6c5bae9 100644
--- a/common/jobs/job_pcb_drc.cpp
+++ b/common/jobs/job_pcb_drc.cpp
@@ -19,10 +19,24 @@
  */
 
 #include <jobs/job_pcb_drc.h>
+#include <jobs/job_registry.h>
+#include <i18n_utility.h>
 
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_PCB_DRC::UNITS,
+                              {
+                                      { JOB_PCB_DRC::UNITS::INCHES, "in" },
+                                      { JOB_PCB_DRC::UNITS::MILLIMETERS, "mm" },
+                                      { JOB_PCB_DRC::UNITS::MILS, "mils" },
+                              } )
+
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_PCB_DRC::OUTPUT_FORMAT,
+                              {
+                                      { JOB_PCB_DRC::OUTPUT_FORMAT::REPORT, "report" },
+                                      { JOB_PCB_DRC::OUTPUT_FORMAT::JSON, "json" },
+                              } )
 
 JOB_PCB_DRC::JOB_PCB_DRC( bool aIsCli ) :
-    JOB( "drc", aIsCli ),
+    JOB( "drc", false, aIsCli ),
     m_filename(),
     m_reportAllTrackErrors( false ),
     m_units( JOB_PCB_DRC::UNITS::MILLIMETERS ),
@@ -31,4 +45,18 @@ JOB_PCB_DRC::JOB_PCB_DRC( bool aIsCli ) :
     m_exitCodeViolations( false ),
     m_parity( true )
 {
-}
\ No newline at end of file
+    m_params.emplace_back( new JOB_PARAM<UNITS>( "units", &m_units, m_units ) );
+    m_params.emplace_back( new JOB_PARAM<int>( "severity", &m_severity, m_severity ) );
+    m_params.emplace_back( new JOB_PARAM<OUTPUT_FORMAT>( "format", &m_format, m_format ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "parity", &m_parity, m_parity ) );
+    m_params.emplace_back( new JOB_PARAM<bool>( "report_all_track_errors", &m_reportAllTrackErrors, m_reportAllTrackErrors ) );
+}
+
+
+wxString JOB_PCB_DRC::GetDescription()
+{
+    return wxString::Format( _( "Perform PCB DRC" ) );
+}
+
+
+REGISTER_JOB( pcb_drc, _HKI( "PCB: Perform DRC" ), KIWAY::FACE_PCB, JOB_PCB_DRC );
\ No newline at end of file
diff --git a/common/jobs/job_pcb_drc.h b/common/jobs/job_pcb_drc.h
index 91cfa3d56f..a1d238fcd7 100644
--- a/common/jobs/job_pcb_drc.h
+++ b/common/jobs/job_pcb_drc.h
@@ -31,6 +31,7 @@ class KICOMMON_API JOB_PCB_DRC : public JOB
 {
 public:
     JOB_PCB_DRC( bool aIsCli );
+    wxString GetDescription() override;
 
     wxString m_filename;
     wxString m_outputFile;
diff --git a/common/jobs/job_pcb_render.cpp b/common/jobs/job_pcb_render.cpp
index 376ab2201d..2dd0c8e302 100644
--- a/common/jobs/job_pcb_render.cpp
+++ b/common/jobs/job_pcb_render.cpp
@@ -23,6 +23,6 @@
 
 
 JOB_PCB_RENDER::JOB_PCB_RENDER( bool aIsCli ) :
-        JOB( "render", aIsCli ), m_filename(), m_outputFile()
+        JOB( "render", false, aIsCli ), m_filename()
 {
 }
\ No newline at end of file
diff --git a/common/jobs/job_registry.cpp b/common/jobs/job_registry.cpp
new file mode 100644
index 0000000000..cfe6c81f97
--- /dev/null
+++ b/common/jobs/job_registry.cpp
@@ -0,0 +1,53 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <jobs/job_registry.h>
+
+bool JOB_REGISTRY::Add( const wxString& aName, JOB_REGISTRY_ENTRY entry )
+{
+    REGISTRY_MAP_T& registry = getRegistry();
+
+    if( registry.find( aName ) != registry.end() )
+    {
+        return false;
+    }
+
+    registry[aName] = entry;
+    return true;
+}
+
+
+KIWAY::FACE_T JOB_REGISTRY::GetKifaceType( const wxString& aName )
+{
+    REGISTRY_MAP_T& registry = getRegistry();
+    if( registry.find( aName ) == registry.end() )
+    {
+        return KIWAY::KIWAY_FACE_COUNT;
+    }
+
+    return registry[aName].kifaceType;
+}
+
+
+JOB_REGISTRY::REGISTRY_MAP_T& JOB_REGISTRY::getRegistry()
+{
+    static REGISTRY_MAP_T map;
+    return map;
+}
\ No newline at end of file
diff --git a/common/jobs/job_registry.h b/common/jobs/job_registry.h
new file mode 100644
index 0000000000..4f529056b2
--- /dev/null
+++ b/common/jobs/job_registry.h
@@ -0,0 +1,70 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <jobs/job.h>
+#include <kiway.h>
+
+struct KICOMMON_API JOB_REGISTRY_ENTRY
+{
+public:
+    KIWAY::FACE_T         kifaceType;
+    std::function<JOB*()> createFunc;
+    wxString              title;
+};
+
+class KICOMMON_API JOB_REGISTRY
+{
+public:
+    typedef std::unordered_map<wxString, JOB_REGISTRY_ENTRY> REGISTRY_MAP_T;
+
+    static bool Add( const wxString& aName, JOB_REGISTRY_ENTRY entry );
+
+    static KIWAY::FACE_T GetKifaceType( const wxString& aName );
+
+    template <typename T>
+    static T* CreateInstance( const wxString& aName )
+    {
+        REGISTRY_MAP_T& registry = getRegistry();
+        if( registry.find( aName ) == registry.end() )
+        {
+            return nullptr;
+        }
+
+        return registry[aName].createFunc();
+    }
+
+    static const REGISTRY_MAP_T& GetRegistry() {
+        return getRegistry();
+    }
+
+private:
+    // Use Meyer's singleton to prevent SIOF
+    static REGISTRY_MAP_T& getRegistry();
+};
+
+#define REGISTER_JOB( job_name, title, face, T ) bool job_name##_entry = JOB_REGISTRY::Add( #job_name, \
+                                                            { face, []()                               \
+                                                            {                                          \
+                                                                return new T( true );                  \
+                                                            },                                         \
+                                                            title } )
+// newline required to appease warning for REGISTER_JOB macro
\ No newline at end of file
diff --git a/common/jobs/job_sch_erc.cpp b/common/jobs/job_sch_erc.cpp
index 722b7dadd2..02dc7a4089 100644
--- a/common/jobs/job_sch_erc.cpp
+++ b/common/jobs/job_sch_erc.cpp
@@ -19,14 +19,40 @@
  */
 
 #include <jobs/job_sch_erc.h>
+#include <jobs/job_registry.h>
+#include <i18n_utility.h>
 
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_SCH_ERC::UNITS,
+                              {
+                                      { JOB_SCH_ERC::UNITS::INCHES, "in" },
+                                      { JOB_SCH_ERC::UNITS::MILLIMETERS, "mm" },
+                                      { JOB_SCH_ERC::UNITS::MILS, "mils" },
+                              } )
+
+NLOHMANN_JSON_SERIALIZE_ENUM( JOB_SCH_ERC::OUTPUT_FORMAT,
+                              {
+                                      { JOB_SCH_ERC::OUTPUT_FORMAT::REPORT, "report" },
+                                      { JOB_SCH_ERC::OUTPUT_FORMAT::JSON, "json" },
+                              } )
 
 JOB_SCH_ERC::JOB_SCH_ERC( bool aIsCli ) :
-    JOB( "erc", aIsCli ),
+    JOB( "erc", false, aIsCli ),
     m_filename(),
     m_units( JOB_SCH_ERC::UNITS::MILLIMETERS ),
     m_severity( RPT_SEVERITY_ERROR | RPT_SEVERITY_WARNING ),
     m_format( OUTPUT_FORMAT::REPORT ),
     m_exitCodeViolations( false )
 {
-}
\ No newline at end of file
+    m_params.emplace_back( new JOB_PARAM<UNITS>( "units", &m_units, m_units ) );
+    m_params.emplace_back( new JOB_PARAM<int>( "severity", &m_severity, m_severity ) );
+    m_params.emplace_back( new JOB_PARAM<OUTPUT_FORMAT>( "format", &m_format, m_format ) );
+}
+
+
+wxString JOB_SCH_ERC::GetDescription()
+{
+    return wxString::Format( _( "Perform Schematic ERC" ) );
+}
+
+
+REGISTER_JOB( sch_erc, _HKI( "Schematic: Perform ERC" ), KIWAY::FACE_SCH, JOB_SCH_ERC );
\ No newline at end of file
diff --git a/common/jobs/job_sch_erc.h b/common/jobs/job_sch_erc.h
index ec00a186c4..5086029e1a 100644
--- a/common/jobs/job_sch_erc.h
+++ b/common/jobs/job_sch_erc.h
@@ -31,6 +31,7 @@ class KICOMMON_API JOB_SCH_ERC : public JOB
 {
 public:
     JOB_SCH_ERC( bool aIsCli );
+    wxString GetDescription() override;
 
     wxString m_filename;
     wxString m_outputFile;
diff --git a/common/jobs/job_sym_export_svg.cpp b/common/jobs/job_sym_export_svg.cpp
index 3bb5e31f38..c8982d2561 100644
--- a/common/jobs/job_sym_export_svg.cpp
+++ b/common/jobs/job_sym_export_svg.cpp
@@ -22,10 +22,9 @@
 
 
 JOB_SYM_EXPORT_SVG::JOB_SYM_EXPORT_SVG( bool aIsCli ) :
-    JOB( "symsvg", aIsCli ),
+    JOB( "symsvg", true, aIsCli ),
     m_libraryPath(),
     m_symbol(),
-    m_outputDirectory(),
     m_blackAndWhite( false ),
     m_includeHiddenPins( false ),
     m_includeHiddenFields( false )
diff --git a/common/jobs/job_sym_upgrade.cpp b/common/jobs/job_sym_upgrade.cpp
index caefc60134..43e923809f 100644
--- a/common/jobs/job_sym_upgrade.cpp
+++ b/common/jobs/job_sym_upgrade.cpp
@@ -22,7 +22,7 @@
 
 
 JOB_SYM_UPGRADE::JOB_SYM_UPGRADE( bool aIsCli ) :
-    JOB( "symupgrade", aIsCli ),
+    JOB( "symupgrade", false, aIsCli ),
     m_libraryPath(),
     m_outputLibraryPath(),
     m_force( false )
diff --git a/common/jobs/jobs_output.h b/common/jobs/jobs_output.h
new file mode 100644
index 0000000000..d2d43216fc
--- /dev/null
+++ b/common/jobs/jobs_output.h
@@ -0,0 +1,48 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <kicommon.h>
+#include <vector>
+#include <jobs/job.h>
+
+class KICOMMON_API JOBS_OUTPUT_HANDLER
+{
+public:
+    JOBS_OUTPUT_HANDLER()
+    {
+    }
+
+    virtual ~JOBS_OUTPUT_HANDLER() {}
+
+    virtual bool HandleOutputs( const wxString&                baseTempPath,
+                                const std::vector<JOB_OUTPUT>& aOutputsToHandle ) = 0;
+
+    virtual void FromJson( const nlohmann::json& j ) = 0;
+    virtual void ToJson( nlohmann::json& j ) const = 0;
+
+
+    void SetOutputPath( const wxString& aPath ) { m_outputPath = aPath; }
+    wxString GetOutputPath() const { return m_outputPath; }
+
+protected:
+    wxString m_outputPath;
+};
\ No newline at end of file
diff --git a/common/jobs/jobs_output_archive.cpp b/common/jobs/jobs_output_archive.cpp
new file mode 100644
index 0000000000..e06424a73b
--- /dev/null
+++ b/common/jobs/jobs_output_archive.cpp
@@ -0,0 +1,76 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <jobs/jobs_output_archive.h>
+#include <wx/fs_zip.h>
+#include <wx/wfstream.h>
+#include <wx/zipstrm.h>
+#include <gestfich.h>
+
+JOBS_OUTPUT_ARCHIVE::JOBS_OUTPUT_ARCHIVE() : JOBS_OUTPUT_HANDLER(),
+    m_format( FORMAT::ZIP )
+{
+}
+
+bool JOBS_OUTPUT_ARCHIVE::HandleOutputs( const wxString&                baseTempPath,
+                                         const std::vector<JOB_OUTPUT>& aOutputsToHandle )
+{
+    bool success = true;
+
+    wxFFileOutputStream ostream( m_outputPath );
+    if( !ostream.IsOk() ) // issue to create the file. Perhaps not writable dir
+    {
+        //msg.Printf( _( "Failed to create file '%s'." ), aDestFile );
+        //aReporter.Report( msg, RPT_SEVERITY_ERROR );
+        return false;
+    }
+
+    wxZipOutputStream zipstream( ostream, -1, wxConvUTF8 );
+    wxString          errors;
+
+
+    if( !AddDirectoryToZip( zipstream, baseTempPath, errors ) )
+    {
+        success = false;
+    }
+
+
+    if( !zipstream.Close() )
+    {
+        success = false;
+    }
+
+
+    return success;
+}
+
+
+void JOBS_OUTPUT_ARCHIVE::FromJson( const nlohmann::json& j )
+{
+	m_outputPath = j.value( "output_path", "" );
+    m_format = FORMAT::ZIP;
+}
+
+
+void JOBS_OUTPUT_ARCHIVE::ToJson( nlohmann::json& j ) const
+{
+    j["output_path"] = m_outputPath;
+	j["format"] = "zip";
+}
\ No newline at end of file
diff --git a/common/jobs/jobs_output_archive.h b/common/jobs/jobs_output_archive.h
new file mode 100644
index 0000000000..65f3946c90
--- /dev/null
+++ b/common/jobs/jobs_output_archive.h
@@ -0,0 +1,45 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <jobs/jobs_output.h>
+
+class KICOMMON_API JOBS_OUTPUT_ARCHIVE : public JOBS_OUTPUT_HANDLER
+{
+public:
+    JOBS_OUTPUT_ARCHIVE();
+
+    enum class FORMAT
+    {
+        ZIP
+    };
+
+    bool HandleOutputs( const wxString& baseTempPath, const std::vector<JOB_OUTPUT>& aOutputsToHandle ) override;
+
+    void FromJson( const nlohmann::json& j ) override;
+    void ToJson( nlohmann::json& j ) const override;
+
+    FORMAT GetFormat() const { return m_format; }
+    void SetFormat( FORMAT format ) { m_format = format; }
+
+private:
+    FORMAT m_format;
+};
\ No newline at end of file
diff --git a/common/jobs/jobs_output_folder.cpp b/common/jobs/jobs_output_folder.cpp
new file mode 100644
index 0000000000..5bf5070c75
--- /dev/null
+++ b/common/jobs/jobs_output_folder.cpp
@@ -0,0 +1,61 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <jobs/jobs_output_folder.h>
+#include <wx/filename.h>
+#include <gestfich.h>
+
+JOBS_OUTPUT_FOLDER::JOBS_OUTPUT_FOLDER() :
+	JOBS_OUTPUT_HANDLER()
+{
+
+}
+
+
+bool JOBS_OUTPUT_FOLDER::HandleOutputs( const wxString&                baseTempPath,
+                                        const std::vector<JOB_OUTPUT>& aOutputsToHandle )
+{
+    bool success = true;
+    if( !wxFileName::Mkdir( m_outputPath, wxS_DIR_DEFAULT ) )
+    {
+        return false;
+    }
+
+    wxString errors;
+    if( !CopyDirectory( baseTempPath, m_outputPath, errors ) )
+    {
+        success = false;
+    }
+
+	return success;
+
+}
+
+
+void JOBS_OUTPUT_FOLDER::FromJson( const nlohmann::json& j )
+{
+	m_outputPath = j.value( "output_path", "" );
+}
+
+
+void JOBS_OUTPUT_FOLDER::ToJson( nlohmann::json& j ) const
+{
+    j["output_path"] = m_outputPath;
+}
\ No newline at end of file
diff --git a/common/jobs/jobs_output_folder.h b/common/jobs/jobs_output_folder.h
new file mode 100644
index 0000000000..4225e39e6a
--- /dev/null
+++ b/common/jobs/jobs_output_folder.h
@@ -0,0 +1,35 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <jobs/jobs_output.h>
+
+class JOBS_OUTPUT_FOLDER : public JOBS_OUTPUT_HANDLER
+{
+public:
+    JOBS_OUTPUT_FOLDER();
+
+    bool HandleOutputs( const wxString&                baseTempPath,
+                        const std::vector<JOB_OUTPUT>& aOutputsToHandle ) override;
+
+    void FromJson( const nlohmann::json& j ) override;
+    void ToJson( nlohmann::json& j ) const override;
+};
\ No newline at end of file
diff --git a/common/jobs/jobset.cpp b/common/jobs/jobset.cpp
new file mode 100644
index 0000000000..0290232820
--- /dev/null
+++ b/common/jobs/jobset.cpp
@@ -0,0 +1,218 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <nlohmann/json.hpp>
+
+#include <settings/parameters.h>
+#include <wildcards_and_files_ext.h>
+
+#include <jobs/jobset.h>
+#include <jobs/job_registry.h>
+#include <jobs/jobs_output_folder.h>
+#include <jobs/jobs_output_archive.h>
+#include <kiid.h>
+
+#include <algorithm>
+
+const int jobsFileSchemaVersion = 1;
+
+NLOHMANN_JSON_SERIALIZE_ENUM( JOBSET_OUTPUT_TYPE,
+                              {
+                                      { JOBSET_OUTPUT_TYPE::FOLDER, "folder" },
+                                      { JOBSET_OUTPUT_TYPE::ARCHIVE, "archive" }
+                              } )
+
+KICOMMON_API void to_json( nlohmann::json& j, const JOBSET_JOB& f )
+{
+    j = nlohmann::json{ { "id", f.m_id },
+                        { "type", f.m_type },
+                        { "settings", nlohmann::json::object( {} ) }
+                      };
+
+    f.m_job->ToJson( j.at( "settings" ) );
+}
+
+
+KICOMMON_API void from_json( const nlohmann::json& j, JOBSET_JOB& f )
+{
+    j.at( "type" ).get_to( f.m_type );
+    j.at( "id" ).get_to( f.m_id );
+
+    nlohmann::json settings_obj = j.at( "settings" );
+
+    f.m_job = JOB_REGISTRY::CreateInstance<JOB>( f.m_type );
+
+    if( f.m_job != nullptr )
+    {
+        f.m_job->FromJson( settings_obj );
+    }
+}
+
+
+KICOMMON_API void to_json( nlohmann::json& j, const JOBSET_OUTPUT& f )
+{
+    j = nlohmann::json{ { "type", f.m_type }, { "settings", nlohmann::json::object( {} ) } };
+
+    f.m_outputHandler->ToJson( j.at( "settings" ) );
+}
+
+
+KICOMMON_API void from_json( const nlohmann::json& j, JOBSET_OUTPUT& f )
+{
+    j.at( "type" ).get_to( f.m_type );
+    f.m_only = j.value( "only", std::vector<wxString>() );
+
+    nlohmann::json settings_obj = j.at( "settings" );
+
+    if( f.m_type == JOBSET_OUTPUT_TYPE::FOLDER )
+    {
+        f.m_outputHandler = new JOBS_OUTPUT_FOLDER();
+    }
+    else if( f.m_type == JOBSET_OUTPUT_TYPE::ARCHIVE )
+    {
+        f.m_outputHandler = new JOBS_OUTPUT_ARCHIVE();
+    }
+
+    if( f.m_outputHandler != nullptr )
+    {
+        f.m_outputHandler->FromJson( settings_obj );
+    }
+}
+
+
+bool JOBSET_JOB::operator==( const JOBSET_JOB & rhs ) const
+{
+    return rhs.m_type == m_type;
+}
+
+
+bool JOBSET_OUTPUT::operator==( const JOBSET_OUTPUT& rhs ) const
+{
+    return rhs.m_type == m_type;
+}
+
+
+JOBSET::JOBSET( const wxString& aFilename ) :
+        JSON_SETTINGS( aFilename, SETTINGS_LOC::NONE, jobsFileSchemaVersion ),
+        m_dirty( false )
+{
+    m_params.emplace_back( new PARAM_LIST<JOBSET_JOB>( "jobs", &m_jobs, {} ) );
+    m_params.emplace_back( new PARAM_LIST<JOBSET_OUTPUT>( "outputs", &m_outputs, {} ) );
+
+    m_fileNameWithoutPath = wxFileName( aFilename ).GetFullName();
+}
+
+
+wxString JOBSET::getFileExt() const
+{
+    return FILEEXT::KiCadJobSetFileExtension;
+}
+
+
+void JOBSET::AddNewJob( wxString aType, JOB* aJob )
+{
+    m_jobs.emplace_back( KIID().AsString(), aType, aJob );
+    SetDirty();
+}
+
+
+JOBSET_OUTPUT JOBSET::AddNewJobOutput( JOBSET_OUTPUT_TYPE aType,
+                                             JOBS_OUTPUT_HANDLER*  aJobOutput )
+{
+    m_outputs.emplace_back( KIID().AsString(), aType, aJobOutput );
+    SetDirty();
+
+    return m_outputs.back();
+}
+
+
+void JOBSET::RemoveOutput( JOBSET_OUTPUT* aOutput )
+{
+    std::erase_if( m_outputs,
+                   [&]( JOBSET_OUTPUT const& output )
+                   {
+                       return output.m_id == aOutput->m_id;
+                   } );
+}
+
+
+bool JOBSET::SaveToFile( const wxString& aDirectory, bool aForce )
+{
+    bool success = JSON_SETTINGS::SaveToFile( aDirectory, aForce );
+    if( success )
+    {
+        m_dirty = false;
+    }
+
+    return success;
+}
+
+
+JOBSET_OUTPUT* JOBSET::GetOutput( wxString& aOutput )
+{
+    auto it = std::find_if( m_outputs.begin(), m_outputs.end(),
+                            [&]( const JOBSET_OUTPUT& output )
+                            {
+                                if( output.m_id == aOutput )
+                                    return true;
+
+                                return false;
+                            } );
+
+    if( it != m_outputs.end() )
+        return &(*it);
+
+    return nullptr;
+}
+
+
+std::vector<JOBSET_JOB> JOBSET::GetJobsForOutput( JOBSET_OUTPUT* aOutput )
+{
+    wxASSERT( aOutput != nullptr );
+
+    if( aOutput->m_only.size() == 0 )
+    {
+        return m_jobs;
+    }
+
+    std::vector<JOBSET_JOB> result;
+    for( wxString& onlyId : aOutput->m_only )
+    {
+        auto it = std::find_if( m_jobs.begin(), m_jobs.end(),
+                                [&]( const JOBSET_JOB& job )
+                                {
+                                    if( job.m_id == onlyId )
+                                        return true;
+
+                                    return false;
+                                } );
+
+        if( it != m_jobs.end() )
+            result.push_back( *it );
+    }
+
+    return result;
+}
+
+
+#if !defined( __MINGW32__ )
+template class KICOMMON_API PARAM_LIST<JOBSET_JOB>;
+template class KICOMMON_API PARAM_LIST<JOBSET_OUTPUT>;
+#endif
\ No newline at end of file
diff --git a/common/jobs/jobset.h b/common/jobs/jobset.h
new file mode 100644
index 0000000000..5b54575781
--- /dev/null
+++ b/common/jobs/jobset.h
@@ -0,0 +1,111 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef JOBS_FILE_H
+#define JOBS_FILE_H
+
+#include <jobs/job.h>
+#include <jobs/jobs_output.h>
+#include <settings/json_settings.h>
+#include <settings/parameters.h>
+#include <ctime>
+
+struct KICOMMON_API JOBSET_JOB
+{
+    wxString m_id;
+    wxString m_type;
+    JOB*     m_job;
+
+    bool operator==( const JOBSET_JOB& rhs ) const;
+};
+
+enum class JOBSET_OUTPUT_TYPE
+{
+    FOLDER,
+    ARCHIVE
+};
+
+struct KICOMMON_API JOBSET_OUTPUT
+{
+    wxString              m_id;
+    JOBSET_OUTPUT_TYPE m_type;
+    JOBS_OUTPUT_HANDLER*  m_outputHandler;
+    std::vector<wxString> m_only;
+
+    bool operator==( const JOBSET_OUTPUT& rhs ) const;
+};
+
+class KICOMMON_API JOBSET : public JSON_SETTINGS
+{
+public:
+    JOBSET( const wxString& aFilename );
+
+    virtual ~JOBSET() {}
+
+    std::vector<JOBSET_JOB>& GetJobs()
+    {
+        return m_jobs;
+    }
+
+    std::vector<JOBSET_JOB> GetJobsForOutput( JOBSET_OUTPUT* aOutput );
+
+    std::vector<JOBSET_OUTPUT>& GetOutputs() { return m_outputs; }
+
+    JOBSET_OUTPUT* GetOutput( wxString& aOutput );
+
+    bool SaveToFile( const wxString& aDirectory = "", bool aForce = false ) override;
+
+    void SetDirty() { m_dirty = true; }
+    bool GetDirty() const { return m_dirty; }
+
+    wxString GetFullName() const { return m_fileNameWithoutPath; }
+
+    void AddNewJob( wxString aType, JOB* aJob );
+    JOBSET_OUTPUT AddNewJobOutput( JOBSET_OUTPUT_TYPE aType,
+                                      JOBS_OUTPUT_HANDLER*  aJobOutput );
+
+    void RemoveOutput( JOBSET_OUTPUT* aOutput );
+
+protected:
+    wxString getFileExt() const override;
+
+private:
+    std::vector<JOBSET_JOB> m_jobs;
+    std::vector<JOBSET_OUTPUT> m_outputs;
+
+    bool m_dirty;
+    wxString m_fileNameWithoutPath;
+};
+
+KICOMMON_API void to_json( nlohmann::json& j, const JOBSET_JOB& f );
+KICOMMON_API void from_json( const nlohmann::json& j, JOBSET_JOB& f );
+
+KICOMMON_API void to_json( nlohmann::json& j, const JOBSET_OUTPUT& f );
+KICOMMON_API void from_json( const nlohmann::json& j, JOBSET_OUTPUT& f );
+
+#if defined( __MINGW32__ )
+template class KICOMMON_API PARAM_LIST<struct JOBSET_JOB>;
+template class KICOMMON_API PARAM_LIST<struct JOBSET_JOB>;
+#else
+extern template class APIVISIBLE PARAM_LIST<JOBSET_JOB>;
+extern template class APIVISIBLE PARAM_LIST<JOBSET_JOB>;
+#endif
+
+#endif
\ No newline at end of file
diff --git a/common/jobs/lset_json.h b/common/jobs/lset_json.h
new file mode 100644
index 0000000000..e2da1692c3
--- /dev/null
+++ b/common/jobs/lset_json.h
@@ -0,0 +1,34 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <lset.h>
+#include <nlohmann/json_fwd.hpp>
+
+
+void to_json( nlohmann::json& aJson, const LSET& aLset )
+{
+    aJson = nlohmann::json( aLset.FmtHex() );
+}
+
+
+void from_json( const nlohmann::json& aJson, LSET& aLset )
+{
+    aLset.ParseHex( aJson.get<std::string>() );
+}
\ No newline at end of file
diff --git a/common/kiway.cpp b/common/kiway.cpp
index 22352e7438..c9082e14c7 100644
--- a/common/kiway.cpp
+++ b/common/kiway.cpp
@@ -714,6 +714,14 @@ int KIWAY::ProcessJob( KIWAY::FACE_T aFace, JOB* job )
 }
 
 
+bool KIWAY::ProcessJobConfigDialog( KIWAY::FACE_T aFace, JOB* aJob, wxWindow* aWindow )
+{
+    KIFACE* kiface = KiFACE( aFace );
+
+    return kiface->HandleJobConfig( aJob, aWindow );
+}
+
+
 void KIWAY::OnKiCadExit()
 {
     if( m_ctl & KFCTL_CPP_PROJECT_SUITE )
diff --git a/common/lset.cpp b/common/lset.cpp
index 442a146b6e..d1084845b0 100644
--- a/common/lset.cpp
+++ b/common/lset.cpp
@@ -349,6 +349,12 @@ std::string LSET::FmtHex() const
 }
 
 
+int LSET::ParseHex( const std::string& str )
+{
+    return ParseHex( str.c_str(), str.length() );
+}
+
+
 int LSET::ParseHex( const char* aStart, int aCount )
 {
     LSET tmp;
diff --git a/common/project/project_local_settings.cpp b/common/project/project_local_settings.cpp
index b006d4ce85..f3b64dd63d 100644
--- a/common/project/project_local_settings.cpp
+++ b/common/project/project_local_settings.cpp
@@ -56,7 +56,7 @@ PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxStrin
             },
             [&]( const std::string& aString )
             {
-                m_VisibleLayers.ParseHex( aString.c_str(), aString.size() );
+                m_VisibleLayers.ParseHex( aString );
             },
             LSET::AllLayersMask().FmtHex() ) );
 
diff --git a/common/settings/settings_manager.cpp b/common/settings/settings_manager.cpp
index 7a6f802c35..1e96a441f8 100644
--- a/common/settings/settings_manager.cpp
+++ b/common/settings/settings_manager.cpp
@@ -1035,6 +1035,12 @@ bool SETTINGS_MANAGER::IsProjectOpen() const
 }
 
 
+bool SETTINGS_MANAGER::IsProjectOpenNotDummy() const
+{
+    return m_projects.size() > 1 || ( m_projects.size() == 1 && !m_projects.begin()->second->GetProjectFullName().IsEmpty() );
+}
+
+
 PROJECT* SETTINGS_MANAGER::GetProject( const wxString& aFullPath ) const
 {
     if( m_projects.count( aFullPath ) )
diff --git a/common/wildcards_and_files_ext.cpp b/common/wildcards_and_files_ext.cpp
index c42ab64a91..92ae265a6c 100644
--- a/common/wildcards_and_files_ext.cpp
+++ b/common/wildcards_and_files_ext.cpp
@@ -155,6 +155,7 @@ const std::string FILEEXT::EquFileExtension( "equ" );
 const std::string FILEEXT::HotkeyFileExtension( "hotkeys" );
 const std::string FILEEXT::DatabaseLibraryFileExtension( "kicad_dbl" );
 const std::string FILEEXT::HTTPLibraryFileExtension( "kicad_httplib" );
+const std::string FILEEXT::KiCadJobSetFileExtension( "kicad_jobset" );
 
 const std::string FILEEXT::ArchiveFileExtension( "zip" );
 
@@ -547,3 +548,9 @@ wxString FILEEXT::HotkeyFileWildcard()
 {
     return _( "Hotkey file" ) + AddFileExtListToFilter( { HotkeyFileExtension } );
 }
+
+
+wxString FILEEXT::JobsetFileWildcard()
+{
+    return _( "KiCad jobset files" ) + AddFileExtListToFilter( { KiCadJobSetFileExtension } );
+}
\ No newline at end of file
diff --git a/eeschema/dialogs/dialog_export_netlist.cpp b/eeschema/dialogs/dialog_export_netlist.cpp
index ae6130c1d0..0270a1b0f3 100644
--- a/eeschema/dialogs/dialog_export_netlist.cpp
+++ b/eeschema/dialogs/dialog_export_netlist.cpp
@@ -48,6 +48,7 @@
 #include <eeschema_settings.h>
 #include <schematic.h>
 #include <paths.h>
+#include <jobs/job_export_sch_netlist.h>
 
 #include <eeschema_id.h>
 #include <wx/checkbox.h>
@@ -81,6 +82,17 @@ enum PANEL_NETLIST_INDEX
 };
 
 
+std::map<JOB_EXPORT_SCH_NETLIST::FORMAT, wxString> jobNetlistNameLookup =
+{
+	{ JOB_EXPORT_SCH_NETLIST::FORMAT::KICADSEXPR,      _( "KiCad" ) },
+    { JOB_EXPORT_SCH_NETLIST::FORMAT::ORCADPCB2, _( "OrcadPCB2" ) },
+    { JOB_EXPORT_SCH_NETLIST::FORMAT::ALLEGRO, _( "Allegro" ) },
+    { JOB_EXPORT_SCH_NETLIST::FORMAT::PADS, _( "PADS" ) },
+    { JOB_EXPORT_SCH_NETLIST::FORMAT::CADSTAR, _( "CadStar" ) },
+    { JOB_EXPORT_SCH_NETLIST::FORMAT::SPICE, _( "SPICE" ) },
+    { JOB_EXPORT_SCH_NETLIST::FORMAT::SPICEMODEL, _( "SPICE Model" ) }
+};
+
 /* wxPanels for creating the NoteBook pages for each netlist format: */
 class EXPORT_NETLIST_PAGE : public wxPanel
 {
@@ -195,7 +207,16 @@ EXPORT_NETLIST_PAGE::EXPORT_NETLIST_PAGE( wxNotebook* aParent, const wxString& a
 
 
 DIALOG_EXPORT_NETLIST::DIALOG_EXPORT_NETLIST( SCH_EDIT_FRAME* aEditFrame ) :
-        DIALOG_EXPORT_NETLIST_BASE( aEditFrame )
+        DIALOG_EXPORT_NETLIST( aEditFrame, aEditFrame )
+{
+
+}
+
+
+DIALOG_EXPORT_NETLIST::DIALOG_EXPORT_NETLIST( SCH_EDIT_FRAME* aEditFrame, wxWindow* aParent,
+                                              JOB_EXPORT_SCH_NETLIST* aJob ) :
+        DIALOG_EXPORT_NETLIST_BASE( aParent ),
+        m_job( aJob )
 {
     m_editFrame = aEditFrame;
 
@@ -235,16 +256,41 @@ DIALOG_EXPORT_NETLIST::DIALOG_EXPORT_NETLIST( SCH_EDIT_FRAME* aEditFrame ) :
 
     InstallPageSpice();
     InstallPageSpiceModel();
-    InstallCustomPages();
 
-    SetupStandardButtons( { { wxID_OK,     _( "Export Netlist" ) },
-                            { wxID_CANCEL, _( "Close" )          } } );
+    wxString selectedPageFormatName;
+    if( !m_job )
+    {
+        m_outputPath->Hide();
+        m_staticTextOutputPath->Hide();
+        InstallCustomPages();
+
+        SetupStandardButtons( { { wxID_OK,     _( "Export Netlist" ) },
+                                { wxID_CANCEL, _( "Close" )          } } );
+
+        selectedPageFormatName = settings.m_NetFormatName;
+    }
+    else
+    {
+        m_MessagesBox->Hide();
+        m_outputPath->SetValue( m_job->GetOutputPath() );
+
+        SetupStandardButtons( { { wxID_OK,     _( "Save" ) },
+                                { wxID_CANCEL, _( "Close" )          } } );
+
+        // custom netlist (external invokes, not supported)
+        auto it = jobNetlistNameLookup.find( m_job->format );
+        if( it != jobNetlistNameLookup.end() )
+			selectedPageFormatName = it->second;
+
+        m_buttonAddGenerator->Hide();
+        m_buttonDelGenerator->Hide();
+    }
 
     for( int ii = 0; ii < DEFINED_NETLISTS_COUNT + CUSTOMPANEL_COUNTMAX; ++ii )
     {
         if( EXPORT_NETLIST_PAGE* candidate = m_PanelNetType[ii] )
         {
-            if( candidate->GetPageNetFmtName() == settings.m_NetFormatName )
+            if( candidate->GetPageNetFmtName() == selectedPageFormatName )
             {
                 m_NoteBook->ChangeSelection( ii );
                 break;
@@ -393,7 +439,6 @@ void DIALOG_EXPORT_NETLIST::OnNetlistTypeSelection( wxNotebookEvent& event )
 bool DIALOG_EXPORT_NETLIST::NetlistUpdateOpt()
 {
     bool changed = false;
-
     bool saveAllVoltages = m_PanelNetType[ PANELSPICE ]->m_SaveAllVoltages->IsChecked();
     bool saveAllCurrents = m_PanelNetType[ PANELSPICE ]->m_SaveAllCurrents->IsChecked();
     bool saveAllDissipations = m_PanelNetType[ PANELSPICE ]->m_SaveAllDissipations->IsChecked();
@@ -402,26 +447,46 @@ bool DIALOG_EXPORT_NETLIST::NetlistUpdateOpt()
     bool curSheetAsRoot = m_PanelNetType[ PANELSPICE ]->m_CurSheetAsRoot->GetValue();
     bool spiceModelCurSheetAsRoot = m_PanelNetType[ PANELSPICEMODEL ]->m_CurSheetAsRoot->GetValue();
 
-    SCHEMATIC_SETTINGS& settings = m_editFrame->Schematic().Settings();
-    wxString netFormatName = m_PanelNetType[m_NoteBook->GetSelection()]->GetPageNetFmtName();
+    if( !m_job )
+    {
+        SCHEMATIC_SETTINGS& settings = m_editFrame->Schematic().Settings();
+        wxString netFormatName = m_PanelNetType[m_NoteBook->GetSelection()]->GetPageNetFmtName();
 
-    changed |= ( settings.m_SpiceSaveAllVoltages != saveAllVoltages );
-    changed |= ( settings.m_SpiceSaveAllCurrents != saveAllCurrents );
-    changed |= ( settings.m_SpiceSaveAllDissipations != saveAllDissipations );
-    changed |= ( settings.m_SpiceSaveAllEvents != saveAllEvents );
-    changed |= ( settings.m_SpiceCommandString != spiceCmdString );
-    changed |= ( settings.m_SpiceCurSheetAsRoot != curSheetAsRoot );
-    changed |= ( settings.m_SpiceModelCurSheetAsRoot != spiceModelCurSheetAsRoot );
-    changed |= ( settings.m_NetFormatName != netFormatName );
+        changed |= ( settings.m_SpiceSaveAllVoltages != saveAllVoltages );
+        changed |= ( settings.m_SpiceSaveAllCurrents != saveAllCurrents );
+        changed |= ( settings.m_SpiceSaveAllDissipations != saveAllDissipations );
+        changed |= ( settings.m_SpiceSaveAllEvents != saveAllEvents );
+        changed |= ( settings.m_SpiceCommandString != spiceCmdString );
+        changed |= ( settings.m_SpiceCurSheetAsRoot != curSheetAsRoot );
+        changed |= ( settings.m_SpiceModelCurSheetAsRoot != spiceModelCurSheetAsRoot );
+        changed |= ( settings.m_NetFormatName != netFormatName );
 
-    settings.m_SpiceSaveAllVoltages     = saveAllVoltages;
-    settings.m_SpiceSaveAllCurrents     = saveAllCurrents;
-    settings.m_SpiceSaveAllDissipations = saveAllDissipations;
-    settings.m_SpiceSaveAllEvents       = saveAllEvents;
-    settings.m_SpiceCommandString       = spiceCmdString;
-    settings.m_SpiceCurSheetAsRoot      = curSheetAsRoot;
-    settings.m_SpiceModelCurSheetAsRoot = spiceModelCurSheetAsRoot;
-    settings.m_NetFormatName            = netFormatName;
+        settings.m_SpiceSaveAllVoltages     = saveAllVoltages;
+        settings.m_SpiceSaveAllCurrents     = saveAllCurrents;
+        settings.m_SpiceSaveAllDissipations = saveAllDissipations;
+        settings.m_SpiceSaveAllEvents       = saveAllEvents;
+        settings.m_SpiceCommandString       = spiceCmdString;
+        settings.m_SpiceCurSheetAsRoot      = curSheetAsRoot;
+        settings.m_SpiceModelCurSheetAsRoot = spiceModelCurSheetAsRoot;
+        settings.m_NetFormatName            = netFormatName;
+    }
+    else
+    {
+        for (auto i = jobNetlistNameLookup.begin(); i != jobNetlistNameLookup.end(); ++i)
+        {
+            if( i->second == m_PanelNetType[m_NoteBook->GetSelection()]->GetPageNetFmtName() )
+            {
+                m_job->format = i->first;
+                break;
+            }
+        }
+
+        m_job->SetOutputPath( m_outputPath->GetValue() );
+        m_job->m_spiceSaveAllVoltages = saveAllVoltages;
+        m_job->m_spiceSaveAllCurrents = saveAllCurrents;
+        m_job->m_spiceSaveAllDissipations = saveAllDissipations;
+        m_job->m_spiceSaveAllEvents = saveAllEvents;
+    }
 
     return changed;
 }
@@ -434,8 +499,18 @@ bool DIALOG_EXPORT_NETLIST::TransferDataFromWindow()
     wxString    fileExt;
     wxString    title = _( "Save Netlist File" );
 
-    if( NetlistUpdateOpt() )
-        m_editFrame->OnModify();
+
+    if (m_job)
+    {
+        NetlistUpdateOpt();
+        return true;
+    }
+    else
+    {
+        if( NetlistUpdateOpt() )
+            m_editFrame->OnModify();
+    }
+
 
     EXPORT_NETLIST_PAGE* currPage;
     currPage = (EXPORT_NETLIST_PAGE*) m_NoteBook->GetCurrentPage();
diff --git a/eeschema/dialogs/dialog_export_netlist.h b/eeschema/dialogs/dialog_export_netlist.h
index acb93084c8..d1606ab4a1 100644
--- a/eeschema/dialogs/dialog_export_netlist.h
+++ b/eeschema/dialogs/dialog_export_netlist.h
@@ -30,13 +30,15 @@
 
 class SCH_EDIT_FRAME;
 class EXPORT_NETLIST_PAGE;
-
+class JOB_EXPORT_SCH_NETLIST;
 
 /* Dialog frame for creating netlists */
 class DIALOG_EXPORT_NETLIST : public DIALOG_EXPORT_NETLIST_BASE
 {
 public:
     DIALOG_EXPORT_NETLIST( SCH_EDIT_FRAME* aEditFrame );
+    DIALOG_EXPORT_NETLIST( SCH_EDIT_FRAME* aEditFrame, wxWindow* aParent,
+                           JOB_EXPORT_SCH_NETLIST* aJob = nullptr );
     ~DIALOG_EXPORT_NETLIST(){};
 
 private:
@@ -82,5 +84,6 @@ private:
 
 private:
     SCH_EDIT_FRAME*      m_editFrame;
+    JOB_EXPORT_SCH_NETLIST*           m_job;
     std::vector<EXPORT_NETLIST_PAGE*> m_PanelNetType;
 };
\ No newline at end of file
diff --git a/eeschema/dialogs/dialog_export_netlist_base.cpp b/eeschema/dialogs/dialog_export_netlist_base.cpp
index cec2b36e78..c2ca48a502 100644
--- a/eeschema/dialogs/dialog_export_netlist_base.cpp
+++ b/eeschema/dialogs/dialog_export_netlist_base.cpp
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
+// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO *NOT* EDIT THIS FILE!
@@ -27,6 +27,21 @@ DIALOG_EXPORT_NETLIST_BASE::DIALOG_EXPORT_NETLIST_BASE( wxWindow* parent, wxWind
 	wxBoxSizer* bUpperSizer;
 	bUpperSizer = new wxBoxSizer( wxVERTICAL );
 
+	wxBoxSizer* bSizer8;
+	bSizer8 = new wxBoxSizer( wxHORIZONTAL );
+
+	m_staticTextOutputPath = new wxStaticText( this, wxID_ANY, _("Output Path:"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_staticTextOutputPath->Wrap( -1 );
+	bSizer8->Add( m_staticTextOutputPath, 0, wxALL, 5 );
+
+	m_outputPath = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+	m_outputPath->SetMinSize( wxSize( 450,-1 ) );
+
+	bSizer8->Add( m_outputPath, 0, wxALL, 5 );
+
+
+	bUpperSizer->Add( bSizer8, 1, wxEXPAND, 5 );
+
 	m_NoteBook = new wxNotebook( this, ID_CHANGE_NOTEBOOK_PAGE, wxDefaultPosition, wxDefaultSize, 0 );
 	m_NoteBook->SetMinSize( wxSize( 540,-1 ) );
 
diff --git a/eeschema/dialogs/dialog_export_netlist_base.fbp b/eeschema/dialogs/dialog_export_netlist_base.fbp
index 16e0c1d758..0d8d48db28 100644
--- a/eeschema/dialogs/dialog_export_netlist_base.fbp
+++ b/eeschema/dialogs/dialog_export_netlist_base.fbp
@@ -1,34 +1,36 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <wxFormBuilder_Project>
-  <FileVersion major="1" minor="17"/>
+  <FileVersion major="1" minor="18"/>
   <object class="Project" expanded="true">
-    <property name="class_decoration"></property>
     <property name="code_generation">C++</property>
-    <property name="disconnect_events">0</property>
-    <property name="disconnect_mode">source_name</property>
-    <property name="disconnect_php_events">0</property>
-    <property name="disconnect_python_events">0</property>
+    <property name="cpp_class_decoration"></property>
+    <property name="cpp_disconnect_events">0</property>
+    <property name="cpp_event_generation">table</property>
+    <property name="cpp_help_provider">none</property>
+    <property name="cpp_namespace"></property>
+    <property name="cpp_precompiled_header"></property>
+    <property name="cpp_use_array_enum">0</property>
+    <property name="cpp_use_enum">1</property>
     <property name="embedded_files_path">res</property>
     <property name="encoding">UTF-8</property>
-    <property name="event_generation">table</property>
     <property name="file">dialog_export_netlist_base</property>
     <property name="first_id">1000</property>
-    <property name="help_provider">none</property>
-    <property name="image_path_wrapper_function_name"></property>
-    <property name="indent_with_spaces"></property>
     <property name="internationalize">1</property>
+    <property name="lua_skip_events">1</property>
+    <property name="lua_ui_table">UI</property>
     <property name="name">DIALOG_EXPORT_NETLIST_BASE</property>
-    <property name="namespace"></property>
     <property name="path">.</property>
-    <property name="precompiled_header"></property>
+    <property name="php_disconnect_events">0</property>
+    <property name="php_disconnect_mode">source_name</property>
+    <property name="php_skip_events">1</property>
+    <property name="python_disconnect_events">0</property>
+    <property name="python_disconnect_mode">source_name</property>
+    <property name="python_image_path_wrapper_function_name"></property>
+    <property name="python_indent_with_spaces"></property>
+    <property name="python_skip_events">1</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_array_enum">0</property>
-    <property name="use_enum">1</property>
     <property name="use_microsoft_bom">0</property>
+    <property name="use_native_eol">0</property>
     <object class="Dialog" expanded="true">
       <property name="aui_managed">0</property>
       <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
@@ -71,6 +73,144 @@
             <property name="name">bUpperSizer</property>
             <property name="orient">wxVERTICAL</property>
             <property name="permission">none</property>
+            <object class="sizeritem" expanded="true">
+              <property name="border">5</property>
+              <property name="flag">wxEXPAND</property>
+              <property name="proportion">1</property>
+              <object class="wxBoxSizer" expanded="true">
+                <property name="minimum_size"></property>
+                <property name="name">bSizer8</property>
+                <property name="orient">wxHORIZONTAL</property>
+                <property name="permission">none</property>
+                <object class="sizeritem" expanded="true">
+                  <property name="border">5</property>
+                  <property name="flag">wxALL</property>
+                  <property name="proportion">0</property>
+                  <object class="wxStaticText" expanded="true">
+                    <property name="BottomDockable">1</property>
+                    <property name="LeftDockable">1</property>
+                    <property name="RightDockable">1</property>
+                    <property name="TopDockable">1</property>
+                    <property name="aui_layer">0</property>
+                    <property name="aui_name"></property>
+                    <property name="aui_position">0</property>
+                    <property name="aui_row">0</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="drag_accept_files">0</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">Output Path:</property>
+                    <property name="markup">0</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_staticTextOutputPath</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"></property>
+                    <property name="window_extra_style"></property>
+                    <property name="window_name"></property>
+                    <property name="window_style"></property>
+                    <property name="wrap">-1</property>
+                  </object>
+                </object>
+                <object class="sizeritem" expanded="true">
+                  <property name="border">5</property>
+                  <property name="flag">wxALL</property>
+                  <property name="proportion">0</property>
+                  <object class="wxTextCtrl" expanded="true">
+                    <property name="BottomDockable">1</property>
+                    <property name="LeftDockable">1</property>
+                    <property name="RightDockable">1</property>
+                    <property name="TopDockable">1</property>
+                    <property name="aui_layer">0</property>
+                    <property name="aui_name"></property>
+                    <property name="aui_position">0</property>
+                    <property name="aui_row">0</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="drag_accept_files">0</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="maxlength">0</property>
+                    <property name="min_size"></property>
+                    <property name="minimize_button">0</property>
+                    <property name="minimum_size">450,-1</property>
+                    <property name="moveable">1</property>
+                    <property name="name">m_outputPath</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"></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="value"></property>
+                    <property name="window_extra_style"></property>
+                    <property name="window_name"></property>
+                    <property name="window_style"></property>
+                  </object>
+                </object>
+              </object>
+            </object>
             <object class="sizeritem" expanded="false">
               <property name="border">5</property>
               <property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
@@ -80,10 +220,10 @@
                 <property name="LeftDockable">1</property>
                 <property name="RightDockable">1</property>
                 <property name="TopDockable">1</property>
-                <property name="aui_layer"></property>
+                <property name="aui_layer">0</property>
                 <property name="aui_name"></property>
-                <property name="aui_position"></property>
-                <property name="aui_row"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</property>
                 <property name="best_size"></property>
                 <property name="bg"></property>
                 <property name="bitmapsize"></property>
@@ -150,10 +290,10 @@
                     <property name="LeftDockable">1</property>
                     <property name="RightDockable">1</property>
                     <property name="TopDockable">1</property>
-                    <property name="aui_layer"></property>
+                    <property name="aui_layer">0</property>
                     <property name="aui_name"></property>
-                    <property name="aui_position"></property>
-                    <property name="aui_row"></property>
+                    <property name="aui_position">0</property>
+                    <property name="aui_row">0</property>
                     <property name="best_size"></property>
                     <property name="bg"></property>
                     <property name="caption"></property>
@@ -221,10 +361,10 @@
                 <property name="LeftDockable">1</property>
                 <property name="RightDockable">1</property>
                 <property name="TopDockable">1</property>
-                <property name="aui_layer"></property>
+                <property name="aui_layer">0</property>
                 <property name="aui_name"></property>
-                <property name="aui_position"></property>
-                <property name="aui_row"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</property>
                 <property name="auth_needed">0</property>
                 <property name="best_size"></property>
                 <property name="bg"></property>
@@ -296,10 +436,10 @@
                 <property name="LeftDockable">1</property>
                 <property name="RightDockable">1</property>
                 <property name="TopDockable">1</property>
-                <property name="aui_layer"></property>
+                <property name="aui_layer">0</property>
                 <property name="aui_name"></property>
-                <property name="aui_position"></property>
-                <property name="aui_row"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</property>
                 <property name="auth_needed">0</property>
                 <property name="best_size"></property>
                 <property name="bg"></property>
@@ -435,10 +575,10 @@
                 <property name="LeftDockable">1</property>
                 <property name="RightDockable">1</property>
                 <property name="TopDockable">1</property>
-                <property name="aui_layer"></property>
+                <property name="aui_layer">0</property>
                 <property name="aui_name"></property>
-                <property name="aui_position"></property>
-                <property name="aui_row"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</property>
                 <property name="best_size"></property>
                 <property name="bg"></property>
                 <property name="caption"></property>
@@ -497,10 +637,10 @@
                 <property name="LeftDockable">1</property>
                 <property name="RightDockable">1</property>
                 <property name="TopDockable">1</property>
-                <property name="aui_layer"></property>
+                <property name="aui_layer">0</property>
                 <property name="aui_name"></property>
-                <property name="aui_position"></property>
-                <property name="aui_row"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</property>
                 <property name="best_size"></property>
                 <property name="bg"></property>
                 <property name="caption"></property>
@@ -562,10 +702,10 @@
                 <property name="LeftDockable">1</property>
                 <property name="RightDockable">1</property>
                 <property name="TopDockable">1</property>
-                <property name="aui_layer"></property>
+                <property name="aui_layer">0</property>
                 <property name="aui_name"></property>
-                <property name="aui_position"></property>
-                <property name="aui_row"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</property>
                 <property name="best_size"></property>
                 <property name="bg"></property>
                 <property name="caption"></property>
@@ -624,10 +764,10 @@
                 <property name="LeftDockable">1</property>
                 <property name="RightDockable">1</property>
                 <property name="TopDockable">1</property>
-                <property name="aui_layer"></property>
+                <property name="aui_layer">0</property>
                 <property name="aui_name"></property>
-                <property name="aui_position"></property>
-                <property name="aui_row"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</property>
                 <property name="best_size"></property>
                 <property name="bg"></property>
                 <property name="caption"></property>
@@ -700,10 +840,10 @@
                 <property name="LeftDockable">1</property>
                 <property name="RightDockable">1</property>
                 <property name="TopDockable">1</property>
-                <property name="aui_layer"></property>
+                <property name="aui_layer">0</property>
                 <property name="aui_name"></property>
-                <property name="aui_position"></property>
-                <property name="aui_row"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</property>
                 <property name="auth_needed">0</property>
                 <property name="best_size"></property>
                 <property name="bg"></property>
diff --git a/eeschema/dialogs/dialog_export_netlist_base.h b/eeschema/dialogs/dialog_export_netlist_base.h
index 3a94be0e86..77da8f7ce1 100644
--- a/eeschema/dialogs/dialog_export_netlist_base.h
+++ b/eeschema/dialogs/dialog_export_netlist_base.h
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
+// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO *NOT* EDIT THIS FILE!
@@ -13,21 +13,21 @@
 class WX_HTML_REPORT_PANEL;
 
 #include "dialog_shim.h"
+#include <wx/string.h>
+#include <wx/stattext.h>
 #include <wx/gdicmn.h>
-#include <wx/notebook.h>
 #include <wx/font.h>
 #include <wx/colour.h>
 #include <wx/settings.h>
-#include <wx/string.h>
-#include <wx/panel.h>
+#include <wx/textctrl.h>
 #include <wx/sizer.h>
+#include <wx/notebook.h>
+#include <wx/panel.h>
 #include <wx/button.h>
 #include <wx/bitmap.h>
 #include <wx/image.h>
 #include <wx/icon.h>
 #include <wx/dialog.h>
-#include <wx/stattext.h>
-#include <wx/textctrl.h>
 
 ///////////////////////////////////////////////////////////////////////////
 
@@ -50,9 +50,11 @@ class DIALOG_EXPORT_NETLIST_BASE : public DIALOG_SHIM
 		{
 			ID_CHANGE_NOTEBOOK_PAGE = 1000,
 			ID_ADD_PLUGIN,
-			ID_DEL_PLUGIN
+			ID_DEL_PLUGIN,
 		};
 
+		wxStaticText* m_staticTextOutputPath;
+		wxTextCtrl* m_outputPath;
 		wxNotebook* m_NoteBook;
 		WX_HTML_REPORT_PANEL* m_MessagesBox;
 		wxBoxSizer* m_buttonSizer;
@@ -91,7 +93,7 @@ class NETLIST_DIALOG_ADD_GENERATOR_BASE : public DIALOG_SHIM
 	protected:
 		enum
 		{
-			wxID_BROWSE_PLUGINS = 1000
+			wxID_BROWSE_PLUGINS = 1000,
 		};
 
 		wxStaticText* m_staticTextName;
diff --git a/eeschema/dialogs/dialog_plot_schematic.cpp b/eeschema/dialogs/dialog_plot_schematic.cpp
index 4956036a64..edf4d9ec08 100644
--- a/eeschema/dialogs/dialog_plot_schematic.cpp
+++ b/eeschema/dialogs/dialog_plot_schematic.cpp
@@ -51,29 +51,47 @@
 #include <kiplatform/environment.h>
 #include <wx/log.h>
 
+#include <jobs/job_export_sch_plot.h>
+
 
 // static members (static to remember last state):
 int DIALOG_PLOT_SCHEMATIC::m_pageSizeSelect = PAGE_SIZE_AUTO;
 HPGL_PAGE_SIZE DIALOG_PLOT_SCHEMATIC::m_HPGLPaperSizeSelect = HPGL_PAGE_SIZE::DEFAULT;
 
 
-DIALOG_PLOT_SCHEMATIC::DIALOG_PLOT_SCHEMATIC( SCH_EDIT_FRAME* parent )
-        : DIALOG_PLOT_SCHEMATIC_BASE( parent ),
-          m_parent( parent ),
+DIALOG_PLOT_SCHEMATIC::DIALOG_PLOT_SCHEMATIC( SCH_EDIT_FRAME* aEditFrame ) :
+        DIALOG_PLOT_SCHEMATIC( aEditFrame, aEditFrame )
+{
+
+}
+
+
+DIALOG_PLOT_SCHEMATIC::DIALOG_PLOT_SCHEMATIC( SCH_EDIT_FRAME* aEditFrame, wxWindow* aParent,
+                                              JOB_EXPORT_SCH_PLOT* aJob )
+        : DIALOG_PLOT_SCHEMATIC_BASE( aEditFrame ),
+          m_editFrame( aEditFrame ),
           m_plotFormat( PLOT_FORMAT::UNDEFINED ),
           m_HPGLPenSize( 1.0 ),
-          m_defaultLineWidth( parent, m_lineWidthLabel, m_lineWidthCtrl, m_lineWidthUnits ),
-          m_penWidth( parent, m_penWidthLabel, m_penWidthCtrl, m_penWidthUnits )
+          m_defaultLineWidth( aEditFrame, m_lineWidthLabel, m_lineWidthCtrl, m_lineWidthUnits ),
+          m_penWidth( aEditFrame, m_penWidthLabel, m_penWidthCtrl, m_penWidthUnits ), m_job( aJob )
 {
     m_configChanged = false;
 
-    m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
-
-    m_MessagesBox->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
-
-    SetupStandardButtons( { { wxID_OK,     _( "Plot All Pages" )    },
-                            { wxID_APPLY,  _( "Plot Current Page" ) },
-                            { wxID_CANCEL, _( "Close" )             } } );
+    if( !m_job )
+    {
+        m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
+        m_MessagesBox->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
+        SetupStandardButtons( { { wxID_OK, _( "Plot All Pages" ) },
+                                { wxID_APPLY, _( "Plot Current Page" ) },
+                                { wxID_CANCEL, _( "Close" ) } } );
+    }
+    else
+    {
+        m_browseButton->Hide();
+        m_MessagesBox->Hide();
+        SetupStandardButtons( { { wxID_OK, _( "Save" ) },
+                                { wxID_CANCEL, _( "Close" ) } } );
+    }
 
     initDlg();
 
@@ -87,72 +105,104 @@ void DIALOG_PLOT_SCHEMATIC::initDlg()
     auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
     wxASSERT( cfg );
 
-    if( cfg )
+    if( !m_job )
     {
-        for( COLOR_SETTINGS* settings : m_parent->GetSettingsManager()->GetColorSettingsList() )
+        if( cfg )
         {
-            int idx = m_colorTheme->Append( settings->GetName(), static_cast<void*>( settings ) );
+            for( COLOR_SETTINGS* settings : m_editFrame->GetSettingsManager()->GetColorSettingsList() )
+            {
+                int idx = m_colorTheme->Append( settings->GetName(), static_cast<void*>( settings ) );
 
-            if( settings->GetFilename() == cfg->m_PlotPanel.color_theme )
-                m_colorTheme->SetSelection( idx );
+                if( settings->GetFilename() == cfg->m_PlotPanel.color_theme )
+                    m_colorTheme->SetSelection( idx );
+            }
+
+            m_colorTheme->Enable( cfg->m_PlotPanel.color );
+
+            m_plotBackgroundColor->Enable( cfg->m_PlotPanel.color );
+            m_plotBackgroundColor->SetValue( cfg->m_PlotPanel.background_color );
+
+            // Set color or B&W plot option
+            setModeColor( cfg->m_PlotPanel.color );
+
+            // Set plot or not frame reference option
+            setPlotDrawingSheet( cfg->m_PlotPanel.frame_reference );
+
+            setOpenFileAfterPlot( cfg->m_PlotPanel.open_file_after_plot );
+
+            m_plotPDFPropertyPopups->SetValue( cfg->m_PlotPanel.pdf_property_popups );
+            m_plotPDFMetadata->SetValue( cfg->m_PlotPanel.pdf_metadata );
+
+            // HPGL plot origin and unit system configuration
+            m_plotOriginOpt->SetSelection( cfg->m_PlotPanel.hpgl_origin );
+
+            m_HPGLPaperSizeSelect = static_cast<HPGL_PAGE_SIZE>( cfg->m_PlotPanel.hpgl_paper_size );
+
+            // HPGL Pen Size is stored in mm in config
+            m_HPGLPenSize = cfg->m_PlotPanel.hpgl_pen_size * schIUScale.IU_PER_MM;
+
+            // Switch to the last save plot format
+            PLOT_FORMAT fmt = static_cast<PLOT_FORMAT>( cfg->m_PlotPanel.format );
+
+            switch( fmt  )
+            {
+            default:
+            case PLOT_FORMAT::POST: m_plotFormatOpt->SetSelection( 0 ); break;
+            case PLOT_FORMAT::PDF:  m_plotFormatOpt->SetSelection( 1 ); break;
+            case PLOT_FORMAT::SVG:  m_plotFormatOpt->SetSelection( 2 ); break;
+            case PLOT_FORMAT::DXF:  m_plotFormatOpt->SetSelection( 3 ); break;
+            case PLOT_FORMAT::HPGL: m_plotFormatOpt->SetSelection( 4 ); break;
+            }
+
+            if( fmt == PLOT_FORMAT::DXF || fmt == PLOT_FORMAT::HPGL )
+                m_plotBackgroundColor->Disable();
+
+            // Set the default line width (pen width which should be used for
+            // items that do not have a pen size defined (like frame ref)
+            // the default line width is stored in mils in config
+            m_defaultLineWidth.SetValue( schIUScale.MilsToIU( cfg->m_Drawing.default_line_thickness ) );
         }
 
-        m_colorTheme->Enable( cfg->m_PlotPanel.color );
+        // Initialize HPGL specific widgets
+        m_penWidth.SetValue( m_HPGLPenSize );
 
-        m_plotBackgroundColor->Enable( cfg->m_PlotPanel.color );
-        m_plotBackgroundColor->SetValue( cfg->m_PlotPanel.background_color );
+        // Plot directory
+        SCHEMATIC_SETTINGS& settings = m_editFrame->Schematic().Settings();
+        wxString            path = settings.m_PlotDirectoryName;
+#ifdef __WINDOWS__
+        path.Replace( '/', '\\' );
+#endif
+        m_outputDirectoryName->SetValue( path );
+    }
+    else if( m_job )
+    {
+        m_plotFormatOpt->SetSelection( static_cast<int>( m_job->m_plotFormat ) );
+		m_plotBackgroundColor->SetValue( m_job->m_useBackgroundColor );
+		m_penWidth.SetValue( m_job->m_HPGLPenSize );
+        m_HPGLPaperSizeSelect = static_cast<HPGL_PAGE_SIZE>( m_job->m_HPGLPaperSizeSelect );
+		m_plotPDFPropertyPopups->SetValue( m_job->m_PDFPropertyPopups );
+		m_plotPDFMetadata->SetValue( m_job->m_PDFMetadata );
+		m_colorTheme->Enable( m_job->m_plotFormat != SCH_PLOT_FORMAT::HPGL );
+		m_ModeColorOption->Enable( m_job->m_plotFormat != SCH_PLOT_FORMAT::HPGL );
+		m_plotOriginOpt->SetSelection( static_cast<int>( m_job->m_HPGLPlotOrigin ) );
+		m_pageSizeSelect = static_cast<int>( m_job->m_pageSizeSelect );
 
-        // Set color or B&W plot option
-        setModeColor( cfg->m_PlotPanel.color );
-
-        // Set plot or not frame reference option
-        setPlotDrawingSheet( cfg->m_PlotPanel.frame_reference );
-
-        setOpenFileAfterPlot( cfg->m_PlotPanel.open_file_after_plot );
-
-        m_plotPDFPropertyPopups->SetValue( cfg->m_PlotPanel.pdf_property_popups );
-        m_plotPDFMetadata->SetValue( cfg->m_PlotPanel.pdf_metadata );
-
-        // HPGL plot origin and unit system configuration
-        m_plotOriginOpt->SetSelection( cfg->m_PlotPanel.hpgl_origin );
-
-        m_HPGLPaperSizeSelect = static_cast<HPGL_PAGE_SIZE>( cfg->m_PlotPanel.hpgl_paper_size );
-
-        // HPGL Pen Size is stored in mm in config
-        m_HPGLPenSize = cfg->m_PlotPanel.hpgl_pen_size * schIUScale.IU_PER_MM;
-
-        // Switch to the last save plot format
-        PLOT_FORMAT fmt = static_cast<PLOT_FORMAT>( cfg->m_PlotPanel.format );
-
-        switch( fmt  )
+        // Set the plot format
+        switch( m_job->m_plotFormat )
         {
         default:
-        case PLOT_FORMAT::POST: m_plotFormatOpt->SetSelection( 0 ); break;
-        case PLOT_FORMAT::PDF:  m_plotFormatOpt->SetSelection( 1 ); break;
-        case PLOT_FORMAT::SVG:  m_plotFormatOpt->SetSelection( 2 ); break;
-        case PLOT_FORMAT::DXF:  m_plotFormatOpt->SetSelection( 3 ); break;
-        case PLOT_FORMAT::HPGL: m_plotFormatOpt->SetSelection( 4 ); break;
+        case SCH_PLOT_FORMAT::POST: m_plotFormatOpt->SetSelection( 0 ); break;
+        case SCH_PLOT_FORMAT::PDF: m_plotFormatOpt->SetSelection( 1 ); break;
+        case SCH_PLOT_FORMAT::SVG: m_plotFormatOpt->SetSelection( 2 ); break;
+        case SCH_PLOT_FORMAT::DXF: m_plotFormatOpt->SetSelection( 3 ); break;
+        case SCH_PLOT_FORMAT::HPGL: m_plotFormatOpt->SetSelection( 4 ); break;
         }
 
-        if( fmt == PLOT_FORMAT::DXF || fmt == PLOT_FORMAT::HPGL )
-            m_plotBackgroundColor->Disable();
+        // And then hide it
+        m_plotFormatOpt->Hide();
 
-        // Set the default line width (pen width which should be used for
-        // items that do not have a pen size defined (like frame ref)
-        // the default line width is stored in mils in config
-        m_defaultLineWidth.SetValue( schIUScale.MilsToIU( cfg->m_Drawing.default_line_thickness ) );
+        m_outputDirectoryName->SetValue( m_job->GetOutputPath() );
     }
-
-    // Initialize HPGL specific widgets
-    m_penWidth.SetValue( m_HPGLPenSize );
-
-    // Plot directory
-    SCHEMATIC_SETTINGS& settings = m_parent->Schematic().Settings();
-    wxString            path     = settings.m_PlotDirectoryName;
-#ifdef __WINDOWS__
-    path.Replace( '/', '\\' );
-#endif
-    m_outputDirectoryName->SetValue( path );
 }
 
 
@@ -185,7 +235,7 @@ void DIALOG_PLOT_SCHEMATIC::OnOutputDirectoryBrowseClicked( wxCommandEvent& even
 
     wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
 
-    wxFileName fn( Prj().AbsolutePath( m_parent->Schematic().Root().GetFileName() ) );
+    wxFileName fn( Prj().AbsolutePath( m_editFrame->Schematic().Root().GetFileName() ) );
     wxString defaultPath = fn.GetPathWithSep();
     wxString msg;
     wxFileName relPathTest; // Used to test if we can make the path relative
@@ -331,7 +381,7 @@ void DIALOG_PLOT_SCHEMATIC::getPlotOptions( RENDER_SETTINGS* aSettings )
     wxString path = m_outputDirectoryName->GetValue();
     path.Replace( '\\', '/' );
 
-    SCHEMATIC_SETTINGS& settings = m_parent->Schematic().Settings();
+    SCHEMATIC_SETTINGS& settings = m_editFrame->Schematic().Settings();
 
     if( settings.m_PlotDirectoryName != path )
         m_configChanged = true;
@@ -346,7 +396,7 @@ COLOR_SETTINGS* DIALOG_PLOT_SCHEMATIC::getColorSettings()
 
     if( selection < 0 )
     {
-        return m_parent->GetSettingsManager()->GetColorSettings(
+        return m_editFrame->GetSettingsManager()->GetColorSettings(
                 COLOR_SETTINGS::COLOR_BUILTIN_DEFAULT );
     }
 
@@ -370,13 +420,13 @@ void DIALOG_PLOT_SCHEMATIC::plotSchematic( bool aPlotAll )
 {
     wxBusyCursor dummy;
 
-    SCH_RENDER_SETTINGS renderSettings( *m_parent->GetRenderSettings() );
+    SCH_RENDER_SETTINGS renderSettings( *m_editFrame->GetRenderSettings() );
     renderSettings.m_ShowHiddenPins = false;
     renderSettings.m_ShowHiddenFields = false;
 
     getPlotOptions( &renderSettings );
 
-    std::unique_ptr<SCH_PLOTTER> schPlotter = std::make_unique<SCH_PLOTTER>( m_parent );
+    std::unique_ptr<SCH_PLOTTER> schPlotter = std::make_unique<SCH_PLOTTER>( m_editFrame );
 
     COLOR_SETTINGS*   colors = getColorSettings();
 
@@ -426,7 +476,7 @@ wxString DIALOG_PLOT_SCHEMATIC::getOutputPath()
     std::function<bool( wxString* )> textResolver =
             [&]( wxString* token ) -> bool
             {
-                SCHEMATIC& schematic = m_parent->Schematic();
+                SCHEMATIC& schematic = m_editFrame->Schematic();
                 return schematic.ResolveTextVar( &schematic.CurrentSheet(), token, 0 );
             };
 
@@ -444,7 +494,7 @@ wxString DIALOG_PLOT_SCHEMATIC::getOutputPath()
     // project path is not defined.
     if( Prj().IsNullProject() )
     {
-        SCH_SCREEN* screen = m_parent->Schematic().RootScreen();
+        SCH_SCREEN* screen = m_editFrame->Schematic().RootScreen();
 
         if( screen && !screen->GetFileName().IsEmpty() )
         {
diff --git a/eeschema/dialogs/dialog_plot_schematic.h b/eeschema/dialogs/dialog_plot_schematic.h
index 822041f8a9..fce4499e82 100644
--- a/eeschema/dialogs/dialog_plot_schematic.h
+++ b/eeschema/dialogs/dialog_plot_schematic.h
@@ -42,11 +42,13 @@ class SCH_EDIT_FRAME;
 class SCH_SCREEN;
 class SCH_SHEET_PATH;
 
+class JOB_EXPORT_SCH_PLOT;
 
 class DIALOG_PLOT_SCHEMATIC : public DIALOG_PLOT_SCHEMATIC_BASE
 {
 public:
-    DIALOG_PLOT_SCHEMATIC( SCH_EDIT_FRAME* parent );
+    DIALOG_PLOT_SCHEMATIC( SCH_EDIT_FRAME* aEditFrame );
+    DIALOG_PLOT_SCHEMATIC( SCH_EDIT_FRAME* aEditFrame, wxWindow* aParent, JOB_EXPORT_SCH_PLOT* aJob = nullptr );
 
     /**
      * Return true if the project configuration was modified.
@@ -142,7 +144,7 @@ private:
      */
     wxString getOutputPath();
 
-    SCH_EDIT_FRAME* m_parent;
+    SCH_EDIT_FRAME* m_editFrame;
     bool            m_configChanged;        // true if a project config param has changed
     PLOT_FORMAT     m_plotFormat;
     static int      m_pageSizeSelect;       // Static to keep last option for some format
@@ -150,6 +152,7 @@ private:
     double             m_HPGLPenSize;
     UNIT_BINDER     m_defaultLineWidth;
     UNIT_BINDER     m_penWidth;
+    JOB_EXPORT_SCH_PLOT*  m_job;
 };
 
 #endif    // __DIALOG_PLOT_SCHEMATIC__
diff --git a/eeschema/eeschema.cpp b/eeschema/eeschema.cpp
index 62342ef68d..600cad28ec 100644
--- a/eeschema/eeschema.cpp
+++ b/eeschema/eeschema.cpp
@@ -346,6 +346,8 @@ static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER
 
     int HandleJob( JOB* aJob ) override;
 
+    bool HandleJobConfig( JOB* aJob, wxWindow* aParent ) override;
+
 private:
     bool loadGlobalLibTable();
     bool loadGlobalDesignBlockLibTable();
@@ -697,3 +699,9 @@ int IFACE::HandleJob( JOB* aJob )
 {
     return m_jobHandler->RunJob( aJob );
 }
+
+
+bool IFACE::HandleJobConfig( JOB* aJob, wxWindow* aParent )
+{
+    return m_jobHandler->HandleJobConfig( aJob, aParent );
+}
\ No newline at end of file
diff --git a/eeschema/eeschema_helpers.cpp b/eeschema/eeschema_helpers.cpp
index c6074baaf5..4c1d0e9b02 100644
--- a/eeschema/eeschema_helpers.cpp
+++ b/eeschema/eeschema_helpers.cpp
@@ -79,8 +79,24 @@ PROJECT* EESCHEMA_HELPERS::GetDefaultProject( bool aSetActive )
 
 
 SCHEMATIC* EESCHEMA_HELPERS::LoadSchematic( const wxString&        aFileName,
-                                            SCH_IO_MGR::SCH_FILE_T aFormat, bool aSetActive,
-                                            bool aForceDefaultProject )
+                                            bool aSetActive,
+                                            bool aForceDefaultProject,
+                                            PROJECT* aProject )
+{
+    if( aFileName.EndsWith( FILEEXT::KiCadSchematicFileExtension ) )
+        return LoadSchematic( aFileName, SCH_IO_MGR::SCH_KICAD, aSetActive, aForceDefaultProject, aProject );
+    else if( aFileName.EndsWith( FILEEXT::LegacySchematicFileExtension ) )
+        return LoadSchematic( aFileName, SCH_IO_MGR::SCH_LEGACY, aSetActive, aForceDefaultProject, aProject );
+
+    // as fall back for any other kind use the legacy format
+    return LoadSchematic( aFileName, SCH_IO_MGR::SCH_LEGACY, aSetActive, aForceDefaultProject, aProject );
+}
+
+
+SCHEMATIC* EESCHEMA_HELPERS::LoadSchematic( const wxString& aFileName, SCH_IO_MGR::SCH_FILE_T aFormat,
+                                            bool aSetActive,
+                                            bool aForceDefaultProject,
+                                            PROJECT* aProject )
 {
     wxFileName pro = aFileName;
     pro.SetExt( FILEEXT::ProjectFileExtension );
@@ -91,7 +107,12 @@ SCHEMATIC* EESCHEMA_HELPERS::LoadSchematic( const wxString&        aFileName,
     // It also avoid wxWidget alerts about locale issues, later, when using Python 3
     LOCALE_IO dummy;
 
-    PROJECT* project = GetSettingsManager()->GetProject( projectPath );
+    PROJECT* project = aProject;
+
+    if( !project )
+    {
+        project = GetSettingsManager()->GetProject( projectPath );
+    }
 
     if( !aForceDefaultProject )
     {
diff --git a/eeschema/eeschema_helpers.h b/eeschema/eeschema_helpers.h
index ac663879ff..f68a65a1eb 100644
--- a/eeschema/eeschema_helpers.h
+++ b/eeschema/eeschema_helpers.h
@@ -44,8 +44,10 @@ public:
     static SETTINGS_MANAGER* GetSettingsManager();
     static void              SetSchEditFrame( SCH_EDIT_FRAME* aSchEditFrame );
     static PROJECT*          GetDefaultProject( bool aSetActive );
+    static SCHEMATIC*        LoadSchematic( const wxString& aFileName, bool aSetActive, bool aForceDefaultProject,
+                                            PROJECT* aProject = nullptr );
     static SCHEMATIC*        LoadSchematic( const wxString& aFileName, SCH_IO_MGR::SCH_FILE_T aFormat,
-                                            bool aSetActive, bool aForceDefaultProject );
+                                            bool aSetActive, bool aForceDefaultProject, PROJECT* aProject = nullptr );
 
 private:
     static SCH_EDIT_FRAME*   s_SchEditFrame;
diff --git a/eeschema/eeschema_jobs_handler.cpp b/eeschema/eeschema_jobs_handler.cpp
index 11da7e1a6a..c0e6e31efd 100644
--- a/eeschema/eeschema_jobs_handler.cpp
+++ b/eeschema/eeschema_jobs_handler.cpp
@@ -67,27 +67,123 @@
 
 #include <fields_data_model.h>
 
+#include <dialogs/dialog_export_netlist.h>
+#include <dialogs/dialog_plot_schematic.h>
+
 
 EESCHEMA_JOBS_HANDLER::EESCHEMA_JOBS_HANDLER( KIWAY* aKiway ) :
-        JOB_DISPATCHER( aKiway )
+        JOB_DISPATCHER( aKiway ),
+        m_cliSchematic( nullptr )
 {
     Register( "bom",
-              std::bind( &EESCHEMA_JOBS_HANDLER::JobExportBom, this, std::placeholders::_1 ) );
+                std::bind( &EESCHEMA_JOBS_HANDLER::JobExportBom, this, std::placeholders::_1 ),
+                [aKiway]( JOB* job, wxWindow* aParent ) -> bool
+                {
+	                JOB_EXPORT_SCH_BOM* bomJob = dynamic_cast<JOB_EXPORT_SCH_BOM*>( job );
+
+	                if( !bomJob )
+		                return false;
+
+                    return false;
+                } );
     Register( "pythonbom",
-              std::bind( &EESCHEMA_JOBS_HANDLER::JobExportPythonBom, this,
-                         std::placeholders::_1 ) );
+                std::bind( &EESCHEMA_JOBS_HANDLER::JobExportPythonBom, this, std::placeholders::_1 ),
+                []( JOB* job, wxWindow* aParent ) -> bool
+                {
+                    return false;
+                });
     Register( "netlist",
-              std::bind( &EESCHEMA_JOBS_HANDLER::JobExportNetlist, this, std::placeholders::_1 ) );
+                std::bind( &EESCHEMA_JOBS_HANDLER::JobExportNetlist, this, std::placeholders::_1 ),
+                [aKiway]( JOB* job, wxWindow* aParent ) -> bool
+                {
+                    JOB_EXPORT_SCH_NETLIST* netJob =
+                            dynamic_cast < JOB_EXPORT_SCH_NETLIST*>( job );
+
+                    if( !netJob )
+                        return false;
+
+                    SCH_EDIT_FRAME* editFrame =
+                            dynamic_cast<SCH_EDIT_FRAME*>( aKiway->Player( FRAME_SCH, false ) );
+
+                    DIALOG_EXPORT_NETLIST dlg( editFrame, aParent, netJob );
+                    dlg.ShowModal();
+
+                    return dlg.GetReturnCode() == wxID_OK;
+                } );
     Register( "plot",
-              std::bind( &EESCHEMA_JOBS_HANDLER::JobExportPlot, this, std::placeholders::_1 ) );
+                std::bind( &EESCHEMA_JOBS_HANDLER::JobExportPlot, this, std::placeholders::_1 ),
+                [aKiway]( JOB* job, wxWindow* aParent ) -> bool
+                {
+                    JOB_EXPORT_SCH_PLOT* plotJob = dynamic_cast<JOB_EXPORT_SCH_PLOT*>( job );
+
+                    if( !plotJob )
+						return false;
+
+                    SCH_EDIT_FRAME* editFrame =
+                            dynamic_cast<SCH_EDIT_FRAME*>( aKiway->Player( FRAME_SCH, false ) );
+
+                    DIALOG_PLOT_SCHEMATIC dlg( editFrame, aParent, plotJob );
+                    dlg.ShowModal();
+
+                    return false;
+                } );
     Register( "symupgrade",
-              std::bind( &EESCHEMA_JOBS_HANDLER::JobSymUpgrade, this, std::placeholders::_1 ) );
+              std::bind( &EESCHEMA_JOBS_HANDLER::JobSymUpgrade, this, std::placeholders::_1 ),
+              []( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  return false;
+              } );
     Register( "symsvg",
-              std::bind( &EESCHEMA_JOBS_HANDLER::JobSymExportSvg, this, std::placeholders::_1 ) );
-    Register( "erc",
-              std::bind( &EESCHEMA_JOBS_HANDLER::JobSchErc, this, std::placeholders::_1 ) );
+              std::bind( &EESCHEMA_JOBS_HANDLER::JobSymExportSvg, this, std::placeholders::_1 ),
+              []( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  return false;
+              } );
+    Register( "erc", std::bind( &EESCHEMA_JOBS_HANDLER::JobSchErc, this, std::placeholders::_1 ),
+              []( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  return false;
+              } );
 }
 
+SCHEMATIC* EESCHEMA_JOBS_HANDLER::getSchematic( const wxString& aPath )
+{
+    SCHEMATIC* sch = nullptr;
+
+    if( !Pgm().IsGUI() && Pgm().GetSettingsManager().IsProjectOpenNotDummy() )
+    {
+        PROJECT& project = Pgm().GetSettingsManager().Prj();
+
+        wxString schPath = aPath;
+        if( schPath.IsEmpty() )
+        {
+            wxFileName path = project.GetProjectFullName();
+            path.SetExt( FILEEXT::KiCadSchematicFileExtension );
+            path.MakeAbsolute();
+            schPath = path.GetFullPath();
+        }
+
+        if( !m_cliSchematic )
+        {
+            m_reporter->Report( _( "Loading schematic\n" ), RPT_SEVERITY_INFO );
+            m_cliSchematic = EESCHEMA_HELPERS::LoadSchematic( schPath, true, false, &project );
+        }
+
+        sch = m_cliSchematic;
+    }
+    else if( !aPath.IsEmpty() )
+    {
+        m_reporter->Report( _( "Loading schematic\n" ), RPT_SEVERITY_INFO );
+        sch = EESCHEMA_HELPERS::LoadSchematic( aPath, true, false );
+    }
+
+    if( !sch )
+    {
+        m_reporter->Report( _( "Failed to load schematic\n" ), RPT_SEVERITY_ERROR );
+    }
+
+    return sch;
+}
 
 void EESCHEMA_JOBS_HANDLER::InitRenderSettings( SCH_RENDER_SETTINGS* aRenderSettings,
                                                 const wxString& aTheme, SCHEMATIC* aSch,
@@ -149,14 +245,10 @@ int EESCHEMA_JOBS_HANDLER::JobExportPlot( JOB* aJob )
     if( !aPlotJob )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
 
-    SCHEMATIC* sch = EESCHEMA_HELPERS::LoadSchematic( aPlotJob->m_filename, SCH_IO_MGR::SCH_KICAD,
-                                                      true, false );
+    SCHEMATIC* sch = getSchematic( aPlotJob->m_filename );
 
-    if( sch == nullptr )
-    {
-        m_reporter->Report( _( "Failed to load schematic file\n" ), RPT_SEVERITY_ERROR );
+    if( !sch )
         return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
-    }
 
     sch->Prj().ApplyTextVars( aJob->GetVarOverrides() );
 
@@ -248,14 +340,10 @@ int EESCHEMA_JOBS_HANDLER::JobExportNetlist( JOB* aJob )
     if( !aNetJob )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
 
-    SCHEMATIC* sch = EESCHEMA_HELPERS::LoadSchematic( aNetJob->m_filename, SCH_IO_MGR::SCH_KICAD,
-                                                      true, false );
+    SCHEMATIC* sch = getSchematic( aNetJob->m_filename );
 
-    if( sch == nullptr )
-    {
-        m_reporter->Report( _( "Failed to load schematic file\n" ), RPT_SEVERITY_ERROR );
+    if( !sch )
         return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
-    }
 
     // Annotation warning check
     SCH_REFERENCE_LIST referenceList;
@@ -335,16 +423,16 @@ int EESCHEMA_JOBS_HANDLER::JobExportNetlist( JOB* aJob )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
     }
 
-    if( aNetJob->m_outputFile.IsEmpty() )
+    if( aNetJob->GetOutputPath().IsEmpty() )
     {
         wxFileName fn = sch->GetFileName();
         fn.SetName( fn.GetName() );
         fn.SetExt( fileExt );
 
-        aNetJob->m_outputFile = fn.GetFullName();
+        aNetJob->SetOutputPath( fn.GetFullName() );
     }
 
-    bool res = helper->WriteNetlist( aNetJob->m_outputFile, netlistOption, *m_reporter );
+    bool res = helper->WriteNetlist( aNetJob->GetOutputPath(), netlistOption, *m_reporter );
 
     if( !res )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
@@ -360,14 +448,10 @@ int EESCHEMA_JOBS_HANDLER::JobExportBom( JOB* aJob )
     if( !aBomJob )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
 
-    SCHEMATIC* sch = EESCHEMA_HELPERS::LoadSchematic( aBomJob->m_filename, SCH_IO_MGR::SCH_KICAD,
-                                                      true, false );
+    SCHEMATIC* sch = getSchematic( aBomJob->m_filename );
 
-    if( sch == nullptr )
-    {
-        m_reporter->Report( _( "Failed to load schematic file\n" ), RPT_SEVERITY_ERROR );
+    if( !sch )
         return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
-    }
 
     sch->Prj().ApplyTextVars( aJob->GetVarOverrides() );
 
@@ -540,21 +624,21 @@ int EESCHEMA_JOBS_HANDLER::JobExportBom( JOB* aJob )
 
     dataModel.ApplyBomPreset( preset );
 
-    if( aBomJob->m_outputFile.IsEmpty() )
+    if( aBomJob->GetOutputPath().IsEmpty() )
     {
         wxFileName fn = sch->GetFileName();
         fn.SetName( fn.GetName() );
         fn.SetExt( FILEEXT::CsvFileExtension );
 
-        aBomJob->m_outputFile = fn.GetFullName();
+        aBomJob->SetOutputPath( fn.GetFullName() );
     }
 
     wxFile f;
 
-    if( !f.Open( aBomJob->m_outputFile, wxFile::write ) )
+    if( !f.Open( aBomJob->GetOutputPath(), wxFile::write ) )
     {
         m_reporter->Report( wxString::Format( _( "Unable to open destination '%s'" ),
-                                              aBomJob->m_outputFile ),
+                                              aBomJob->GetOutputPath() ),
                             RPT_SEVERITY_ERROR );
 
         return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
@@ -619,14 +703,10 @@ int EESCHEMA_JOBS_HANDLER::JobExportPythonBom( JOB* aJob )
     if( !aNetJob )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
 
-    SCHEMATIC* sch = EESCHEMA_HELPERS::LoadSchematic( aNetJob->m_filename, SCH_IO_MGR::SCH_KICAD,
-                                                      true, false );
+    SCHEMATIC* sch = getSchematic( aNetJob->m_filename );
 
-    if( sch == nullptr )
-    {
-        m_reporter->Report( _( "Failed to load schematic file\n" ), RPT_SEVERITY_ERROR );
+    if( !sch )
         return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
-    }
 
     // Annotation warning check
     SCH_REFERENCE_LIST referenceList;
@@ -657,16 +737,16 @@ int EESCHEMA_JOBS_HANDLER::JobExportPythonBom( JOB* aJob )
     std::unique_ptr<NETLIST_EXPORTER_XML> xmlNetlist =
             std::make_unique<NETLIST_EXPORTER_XML>( sch );
 
-    if( aNetJob->m_outputFile.IsEmpty() )
+    if( aNetJob->GetOutputPath().IsEmpty() )
     {
         wxFileName fn = sch->GetFileName();
         fn.SetName( fn.GetName() + "-bom" );
         fn.SetExt( FILEEXT::XmlFileExtension );
 
-        aNetJob->m_outputFile = fn.GetFullName();
+        aNetJob->SetOutputPath( fn.GetFullName() );
     }
 
-    bool res = xmlNetlist->WriteNetlist( aNetJob->m_outputFile, GNL_OPT_BOM, *m_reporter );
+    bool res = xmlNetlist->WriteNetlist( aNetJob->GetOutputPath(), GNL_OPT_BOM, *m_reporter );
 
     if( !res )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
@@ -967,14 +1047,10 @@ int EESCHEMA_JOBS_HANDLER::JobSchErc( JOB* aJob )
     if( !ercJob )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
 
-    SCHEMATIC* sch = EESCHEMA_HELPERS::LoadSchematic( ercJob->m_filename, SCH_IO_MGR::SCH_KICAD,
-                                                      true, false );
+    SCHEMATIC* sch = getSchematic( ercJob->m_filename );
 
-    if( sch == nullptr )
-    {
-        m_reporter->Report( _( "Failed to load schematic file\n" ), RPT_SEVERITY_ERROR );
+    if( !sch )
         return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
-    }
 
     sch->Prj().ApplyTextVars( aJob->GetVarOverrides() );
 
diff --git a/eeschema/eeschema_jobs_handler.h b/eeschema/eeschema_jobs_handler.h
index f06ab85974..df5a96841c 100644
--- a/eeschema/eeschema_jobs_handler.h
+++ b/eeschema/eeschema_jobs_handler.h
@@ -62,11 +62,14 @@ public:
                              const wxString& aDrawingSheetOverride = wxEmptyString );
 
 private:
+    SCHEMATIC* getSchematic( const wxString& aPath );
 
     int doSymExportSvg( JOB_SYM_EXPORT_SVG* aSvgJob, SCH_RENDER_SETTINGS* aRenderSettings,
                         LIB_SYMBOL* symbol );
 
     DS_PROXY_VIEW_ITEM* getDrawingSheetProxyView( SCHEMATIC* aSch );
+
+    SCHEMATIC* m_cliSchematic;
 };
 
 #endif
diff --git a/include/advanced_config.h b/include/advanced_config.h
index 1023be96fa..02c4814bd9 100644
--- a/include/advanced_config.h
+++ b/include/advanced_config.h
@@ -493,6 +493,15 @@ public:
      */
     bool m_EnableGit;
 
+    /**
+     * Enable jobsets
+     *
+     * Setting name: "EnableJobs"
+     * Valid values: 0 or 1
+     * Default value: 0
+     */
+    bool m_EnableJobset;
+
     /**
      * Enable option to load lib files with text editor.
      *
diff --git a/include/cli/exit_codes.h b/include/cli/exit_codes.h
index 3a1c2909ad..7475cc15d2 100644
--- a/include/cli/exit_codes.h
+++ b/include/cli/exit_codes.h
@@ -25,15 +25,16 @@ namespace CLI
 {
     namespace EXIT_CODES
     {
-        static const int  AVOID_CLOSING = -1;
-        static const int  SUCCESS = 0;
-        static const int  OK = 0;
-        static const int  ERR_ARGS = 1;
-        static const int  ERR_UNKNOWN = 2;
-        static const int  ERR_INVALID_INPUT_FILE = 3;
-        static const int  ERR_INVALID_OUTPUT_CONFLICT = 4;
+        static const int AVOID_CLOSING = -1;
+        static const int SUCCESS = 0;
+        static const int OK = 0;
+        static const int ERR_ARGS = 1;
+        static const int ERR_UNKNOWN = 2;
+        static const int ERR_INVALID_INPUT_FILE = 3;
+        static const int ERR_INVALID_OUTPUT_CONFLICT = 4;
         ///< Rules check violation count was greater than 0
-        static const int  ERR_RC_VIOLATIONS = 5;
+        static const int ERR_RC_VIOLATIONS = 5;
+        static const int ERR_JOBS_RUN_FAILED = 6;
     };
 }
 
diff --git a/include/gestfich.h b/include/gestfich.h
index a4a75291ac..b8c69d6367 100644
--- a/include/gestfich.h
+++ b/include/gestfich.h
@@ -28,6 +28,7 @@
 #include <kicommon.h>
 #include <wx/filename.h>
 #include <wx/process.h>
+#include <wx/zipstrm.h>
 
 
 /**
@@ -107,4 +108,28 @@ KICOMMON_API extern wxString QuoteFullPath( wxFileName& fn, wxPathFormat format
  */
 KICOMMON_API bool RmDirRecursive( const wxString& aDirName, wxString* aErrors = nullptr );
 
+/**
+ * Copy a directory and its contents to another directory.
+ *
+ * @param aSourceDir is the directory to copy.
+ * @param aDestDir is the directory to copy to.
+ * @param aErrors is a string to append any errors to.
+ */
+KICOMMON_API bool CopyDirectory( const wxString& aSourceDir, const wxString& aDestDir,
+                                 wxString& aErrors );
+
+
+/**
+ * Add a directory and its contents to a zip file.
+ *
+ * @param aZip is the zip file to add to.
+ * @param aSourceDir is the directory to add.
+ * @param aErrors is a string to append any errors to.
+ * @param aParentDir is the parent directory to add to the zip file.
+ */
+KICOMMON_API bool AddDirectoryToZip( wxZipOutputStream& aZip,
+                                     const wxString& aSourceDir,
+                                     wxString& aErrors,
+                                     const wxString& aParentDir = "" );
+
 #endif /* GESTFICH_H */
diff --git a/include/kiway.h b/include/kiway.h
index b6ab629a2c..dbbdfd1564 100644
--- a/include/kiway.h
+++ b/include/kiway.h
@@ -104,7 +104,6 @@
 #include <frame_type.h>
 #include <mail_type.h>
 #include <ki_exception.h>
-#include <jobs/job.h>
 
 
 #define KIFACE_VERSION      1
@@ -133,6 +132,7 @@ class KIWAY;
 class KIWAY_PLAYER;
 class wxTopLevelWindow;
 class TOOL_ACTION;
+class JOB;
 
 
 /**
@@ -245,6 +245,11 @@ struct KIFACE
     {
         return 0;
     }
+
+    virtual bool HandleJobConfig( JOB* aJob, wxWindow* aParent )
+    {
+        return 0;
+    }
 };
 
 
@@ -426,7 +431,8 @@ public:
 
     bool ProcessEvent( wxEvent& aEvent ) override;
 
-    int ProcessJob( KIWAY::FACE_T aFace, JOB* job );
+    int ProcessJob( KIWAY::FACE_T aFace, JOB* aJob );
+    bool ProcessJobConfigDialog( KIWAY::FACE_T aFace, JOB* aJob, wxWindow* aWindow );
 
     /**
      * Gets the window pointer to the blocking dialog (to send it signals)
diff --git a/include/lset.h b/include/lset.h
index 02f348e71b..5ded02a3bb 100644
--- a/include/lset.h
+++ b/include/lset.h
@@ -260,6 +260,7 @@ public:
      * @return int - number of bytes consumed
      */
     int ParseHex( const char* aStart, int aCount );
+    int ParseHex( const std::string& str );
 
     /**
      * Return a binary string showing contents of this LSEQ.
diff --git a/include/settings/settings_manager.h b/include/settings/settings_manager.h
index a83174b902..d2615e0697 100644
--- a/include/settings/settings_manager.h
+++ b/include/settings/settings_manager.h
@@ -287,6 +287,12 @@ public:
      */
     bool IsProjectOpen() const;
 
+    /**
+     * Helper for checking if we have a project open that is not a dummy project
+     * @return true if a call to Prj() will succeed and the project is not a dummy project
+     */
+    bool IsProjectOpenNotDummy() const;
+
     /**
      * A helper while we are not MDI-capable -- return the one and only project
      * @return the loaded project
diff --git a/include/wildcards_and_files_ext.h b/include/wildcards_and_files_ext.h
index 796d1be2bf..3bbcbbcc44 100644
--- a/include/wildcards_and_files_ext.h
+++ b/include/wildcards_and_files_ext.h
@@ -193,6 +193,8 @@ public:
     static const std::string BrepFileExtension;
     static const std::string XaoFileExtension;
 
+    static const std::string KiCadJobSetFileExtension;
+
     static const wxString GerberFileExtensionsRegex;
 
     static const std::string KiCadUriPrefix;
@@ -269,6 +271,7 @@ public:
     static wxString PngFileWildcard();
     static wxString JpegFileWildcard();
     static wxString HotkeyFileWildcard();
+    static wxString JobsetFileWildcard();
 
     /**
      * @}
diff --git a/kicad/CMakeLists.txt b/kicad/CMakeLists.txt
index 69e888ff94..9b03358f0c 100644
--- a/kicad/CMakeLists.txt
+++ b/kicad/CMakeLists.txt
@@ -25,7 +25,11 @@ set( KICAD_SRCS
     dialogs/dialog_template_selector.cpp
     dialogs/panel_kicad_launcher_base.cpp
     dialogs/panel_kicad_launcher.cpp
+    dialogs/dialog_job_config_base.cpp
+    dialogs/panel_jobs_base.cpp
+    dialogs/panel_jobs.cpp
     files-io.cpp
+    jobs_runner.cpp
     import_proj.cpp
     import_project.cpp
     kicad_manager_frame.cpp
@@ -41,6 +45,7 @@ set( KICAD_SRCS
 
 set( KICAD_CLI_SRCS
     cli/command.cpp
+    cli/command_jobset_run.cpp
     cli/command_pcb_export_base.cpp
     cli/command_pcb_drc.cpp
     cli/command_pcb_render.cpp
@@ -64,6 +69,8 @@ set( KICAD_CLI_SRCS
     cli/command_sym_export_svg.cpp
     cli/command_sym_upgrade.cpp
     cli/command_version.cpp
+
+    jobs_runner.cpp
     )
 
 if( WIN32 )
diff --git a/kicad/cli/command_jobset.h b/kicad/cli/command_jobset.h
new file mode 100644
index 0000000000..a3b21e3cba
--- /dev/null
+++ b/kicad/cli/command_jobset.h
@@ -0,0 +1,37 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2022 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 1992-2022 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef COMMAND_JOBS_H
+#define COMMAND_JOBS_H
+
+#include "command.h"
+
+namespace CLI
+{
+struct JOBSET_COMMAND : public COMMAND
+{
+    JOBSET_COMMAND() : COMMAND( "jobset" )
+    {
+        m_argParser.add_description( UTF8STDSTR( _( "Jobset" ) ) );
+    }
+};
+}
+
+#endif
\ No newline at end of file
diff --git a/kicad/cli/command_jobset_run.cpp b/kicad/cli/command_jobset_run.cpp
new file mode 100644
index 0000000000..4693225a5e
--- /dev/null
+++ b/kicad/cli/command_jobset_run.cpp
@@ -0,0 +1,102 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "command_jobset_run.h"
+#include <cli/exit_codes.h>
+#include <kiface_base.h>
+#include <layer_ids.h>
+#include <string_utils.h>
+#include <wx/crt.h>
+#include <jobs/jobset.h>
+#include <jobs/job_registry.h>
+#include <pgm_base.h>
+#include <settings/settings_manager.h>
+
+#include <macros.h>
+#include <wx/tokenzr.h>
+#include <jobs_runner.h>
+#include <reporter.h>
+
+#define ARG_STOP_ON_ERROR "--stop-on-error"
+#define ARG_JOB_FILE "--file"
+#define ARG_OUTPUT "--output"
+
+CLI::JOBSET_RUN_COMMAND::JOBSET_RUN_COMMAND() : COMMAND( "run" )
+{
+    addCommonArgs( true, false, false, false );
+
+    m_argParser.add_description( UTF8STDSTR( _( "Runs a jobset file" ) ) );
+
+    m_argParser.add_argument( ARG_STOP_ON_ERROR )
+            .help( UTF8STDSTR(
+                    _( "Stops processing jobs as they are executed sequentially on the first failure of a job" ) ) )
+            .flag();
+
+    m_argParser.add_argument( ARG_JOB_FILE, "-f" )
+            .help( UTF8STDSTR( _( "Jobset file to be run" ) ) )
+            .default_value( std::string( "" ) )
+            .metavar( "JOB_FILE" );
+
+    m_argParser.add_argument( ARG_OUTPUT )
+            .help( UTF8STDSTR( _( "Jobset file output to generate, leave blank for all outputs defined in the jobset" ) ) )
+            .default_value( std::string( "" ) )
+            .metavar( "OUTPUT" );
+}
+
+
+int CLI::JOBSET_RUN_COMMAND::doPerform( KIWAY& aKiway )
+{
+    bool bail = m_argParser.get<bool>( ARG_STOP_ON_ERROR );
+    wxString jobsFilePath = From_UTF8( m_argParser.get<std::string>( ARG_JOB_FILE ).c_str() );
+    wxString  projectFile = m_argInput.ToStdString();
+
+    wxString outputKey = From_UTF8( m_argParser.get<std::string>( ARG_OUTPUT ).c_str() );
+
+    if( !Pgm().GetSettingsManager().LoadProject( projectFile ) )
+    {
+        return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
+    }
+
+    JOBSET jobFile( jobsFilePath.ToStdString() );
+
+    jobFile.LoadFromFile();
+
+    JOBS_RUNNER  jobsRunner( &aKiway, &jobFile, &CLI_REPORTER::GetInstance() );
+
+    int return_code = CLI::EXIT_CODES::SUCCESS;
+
+    if( !outputKey.IsEmpty() )
+    {
+        JOBSET_OUTPUT* output = jobFile.GetOutput( outputKey );
+        if( output == nullptr || !jobsRunner.RunJobsForOutput( output, bail ) )
+        {
+            return_code = CLI::EXIT_CODES::ERR_JOBS_RUN_FAILED;
+        }
+    }
+    else
+    {
+        if( !jobsRunner.RunJobsAllOutputs( bail ) )
+        {
+            return_code = CLI::EXIT_CODES::ERR_JOBS_RUN_FAILED;
+        }
+    }
+
+    return return_code;
+}
diff --git a/kicad/cli/command_jobset_run.h b/kicad/cli/command_jobset_run.h
new file mode 100644
index 0000000000..dec974649a
--- /dev/null
+++ b/kicad/cli/command_jobset_run.h
@@ -0,0 +1,35 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "command_pcb_export_base.h"
+
+namespace CLI
+{
+class JOBSET_RUN_COMMAND : public COMMAND
+{
+public:
+    JOBSET_RUN_COMMAND();
+
+protected:
+    int doPerform( KIWAY& aKiway ) override;
+};
+}
\ No newline at end of file
diff --git a/kicad/cli/command_pcb_export_3d.cpp b/kicad/cli/command_pcb_export_3d.cpp
index 494faa2ae4..4e1755dff5 100644
--- a/kicad/cli/command_pcb_export_3d.cpp
+++ b/kicad/cli/command_pcb_export_3d.cpp
@@ -236,7 +236,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 );
-    params.m_OutputFile = m_argOutput;
+    step->SetOutputPath( 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 f5b5bfba1a..5e13176101 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( true ) );
 
     drillJob->m_filename = m_argInput;
-    drillJob->m_outputDir = m_argOutput;
+    drillJob->SetOutputPath( m_argOutput );
 
-    if( !drillJob->m_outputDir.IsEmpty() )
+    if( !drillJob->GetOutputPath().IsEmpty() )
     {
-        wxFileName fn( drillJob->m_outputDir, wxEmptyString );
+        wxFileName fn( drillJob->GetOutputPath(), wxEmptyString );
 
         if( !fn.IsDir() )
         {
diff --git a/kicad/cli/command_pcb_export_dxf.cpp b/kicad/cli/command_pcb_export_dxf.cpp
index 709c05a2c6..aaaa960399 100644
--- a/kicad/cli/command_pcb_export_dxf.cpp
+++ b/kicad/cli/command_pcb_export_dxf.cpp
@@ -79,7 +79,7 @@ int CLI::PCB_EXPORT_DXF_COMMAND::doPerform( KIWAY& aKiway )
     std::unique_ptr<JOB_EXPORT_PCB_DXF> dxfJob( new JOB_EXPORT_PCB_DXF( true ) );
 
     dxfJob->m_filename = m_argInput;
-    dxfJob->m_outputFile = m_argOutput;
+    dxfJob->SetOutputPath( m_argOutput );
     dxfJob->m_drawingSheet = m_argDrawingSheet;
     dxfJob->SetVarOverrides( m_argDefineVars );
 
@@ -93,7 +93,7 @@ int CLI::PCB_EXPORT_DXF_COMMAND::doPerform( KIWAY& aKiway )
     dxfJob->m_plotRefDes = !m_argParser.get<bool>( ARG_EXCLUDE_REFDES );
     dxfJob->m_plotGraphicItemsUsingContours = m_argParser.get<bool>( ARG_USE_CONTOURS );
     dxfJob->m_useDrillOrigin = m_argParser.get<bool>( ARG_USE_DRILL_ORIGIN );
-    dxfJob->m_plotBorderTitleBlocks = m_argParser.get<bool>( ARG_INCLUDE_BORDER_TITLE );
+    dxfJob->m_plotDrawingSheet = m_argParser.get<bool>( ARG_INCLUDE_BORDER_TITLE );
 
     wxString units = From_UTF8( m_argParser.get<std::string>( ARG_OUTPUT_UNITS ).c_str() );
 
diff --git a/kicad/cli/command_pcb_export_gencad.cpp b/kicad/cli/command_pcb_export_gencad.cpp
index f7ac912001..34b4b8e887 100644
--- a/kicad/cli/command_pcb_export_gencad.cpp
+++ b/kicad/cli/command_pcb_export_gencad.cpp
@@ -78,7 +78,6 @@ int CLI::PCB_EXPORT_GENCAD_COMMAND::doPerform( KIWAY& aKiway )
     std::unique_ptr<JOB_EXPORT_PCB_GENCAD> gencadJob( new JOB_EXPORT_PCB_GENCAD( true ) );
 
     gencadJob->m_filename = m_argInput;
-    gencadJob->m_outputFile = m_argOutput;
     gencadJob->SetVarOverrides( m_argDefineVars );
 
     gencadJob->m_flipBottomPads = m_argParser.get<bool>( ARG_FLIP_BOTTOM_PADS );
diff --git a/kicad/cli/command_pcb_export_gerber.cpp b/kicad/cli/command_pcb_export_gerber.cpp
index 001d5b4e47..ff6c287c24 100644
--- a/kicad/cli/command_pcb_export_gerber.cpp
+++ b/kicad/cli/command_pcb_export_gerber.cpp
@@ -93,13 +93,13 @@ 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->m_outputFile = m_argOutput;
+    aJob->SetOutputPath( m_argOutput );
     aJob->m_drawingSheet = m_argDrawingSheet;
     aJob->SetVarOverrides( m_argDefineVars );
 
     aJob->m_plotFootprintValues = !m_argParser.get<bool>( ARG_EXCLUDE_VALUE );
     aJob->m_plotRefDes = !m_argParser.get<bool>( ARG_EXCLUDE_REFDES );
-    aJob->m_plotBorderTitleBlocks = m_argParser.get<bool>( ARG_INCLUDE_BORDER_TITLE );
+    aJob->m_plotDrawingSheet = m_argParser.get<bool>( ARG_INCLUDE_BORDER_TITLE );
     aJob->m_disableApertureMacros = m_argParser.get<bool>( ARG_DISABLE_APERTURE_MACROS );
     aJob->m_subtractSolderMaskFromSilk = m_argParser.get<bool>( ARG_SUBTRACT_SOLDERMASK );
     aJob->m_includeNetlistAttributes = !m_argParser.get<bool>( ARG_NO_NETLIST );
diff --git a/kicad/cli/command_pcb_export_ipc2581.cpp b/kicad/cli/command_pcb_export_ipc2581.cpp
index ba205bf7a6..8c0e104494 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( true ) );
 
     ipc2581Job->m_filename = m_argInput;
-    ipc2581Job->m_outputFile = m_argOutput;
+    ipc2581Job->SetOutputPath( m_argOutput );
     ipc2581Job->m_drawingSheet = m_argDrawingSheet;
     ipc2581Job->SetVarOverrides( m_argDefineVars );
 
diff --git a/kicad/cli/command_pcb_export_pdf.cpp b/kicad/cli/command_pcb_export_pdf.cpp
index 6e23644136..c4cbdd613c 100644
--- a/kicad/cli/command_pcb_export_pdf.cpp
+++ b/kicad/cli/command_pcb_export_pdf.cpp
@@ -99,7 +99,7 @@ int CLI::PCB_EXPORT_PDF_COMMAND::doPerform( KIWAY& aKiway )
     std::unique_ptr<JOB_EXPORT_PCB_PDF> pdfJob( new JOB_EXPORT_PCB_PDF( true ) );
 
     pdfJob->m_filename = m_argInput;
-    pdfJob->m_outputFile = m_argOutput;
+    pdfJob->SetOutputPath( m_argOutput );
     pdfJob->m_drawingSheet = m_argDrawingSheet;
     pdfJob->SetVarOverrides( m_argDefineVars );
 
@@ -112,7 +112,7 @@ int CLI::PCB_EXPORT_PDF_COMMAND::doPerform( KIWAY& aKiway )
     pdfJob->m_plotFootprintValues = !m_argParser.get<bool>( ARG_EXCLUDE_VALUE );
     pdfJob->m_plotRefDes = !m_argParser.get<bool>( ARG_EXCLUDE_REFDES );
 
-    pdfJob->m_plotBorderTitleBlocks = m_argParser.get<bool>( ARG_INCLUDE_BORDER_TITLE );
+    pdfJob->m_plotDrawingSheet = m_argParser.get<bool>( ARG_INCLUDE_BORDER_TITLE );
 
     pdfJob->m_mirror = m_argParser.get<bool>( ARG_MIRROR );
     pdfJob->m_blackAndWhite = m_argParser.get<bool>( ARG_BLACKANDWHITE );
diff --git a/kicad/cli/command_pcb_export_pos.cpp b/kicad/cli/command_pcb_export_pos.cpp
index 99217a2f41..dee661e497 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( true ) );
 
     aPosJob->m_filename = m_argInput;
-    aPosJob->m_outputFile = m_argOutput;
+    aPosJob->SetOutputPath( 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 ae2f652180..5fd8870f2a 100644
--- a/kicad/cli/command_pcb_export_svg.cpp
+++ b/kicad/cli/command_pcb_export_svg.cpp
@@ -114,7 +114,7 @@ int CLI::PCB_EXPORT_SVG_COMMAND::doPerform( KIWAY& aKiway )
     svgJob->m_drawingSheet = m_argDrawingSheet;
 
     svgJob->m_filename = m_argInput;
-    svgJob->m_outputFile = m_argOutput;
+    svgJob->SetOutputPath( 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_sch_export_bom.cpp b/kicad/cli/command_sch_export_bom.cpp
index b646a6a51c..4c98e652a8 100644
--- a/kicad/cli/command_sch_export_bom.cpp
+++ b/kicad/cli/command_sch_export_bom.cpp
@@ -134,7 +134,7 @@ int CLI::SCH_EXPORT_BOM_COMMAND::doPerform( KIWAY& aKiway )
 
     // Basic options
     bomJob->m_filename = m_argInput;
-    bomJob->m_outputFile = m_argOutput;
+    bomJob->SetOutputPath( 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 da35a64aee..1be9fe6a01 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>( true );
 
     netJob->m_filename = m_argInput;
-    netJob->m_outputFile = m_argOutput;
+    netJob->SetOutputPath( 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 4d925fd4a3..9772915354 100644
--- a/kicad/cli/command_sch_export_plot.cpp
+++ b/kicad/cli/command_sch_export_plot.cpp
@@ -137,8 +137,9 @@ int CLI::SCH_EXPORT_PLOT_COMMAND::doPerform( KIWAY& aKiway )
     }
 
     std::unique_ptr<JOB_EXPORT_SCH_PLOT> plotJob =
-            std::make_unique<JOB_EXPORT_SCH_PLOT>( true, m_plotFormat, filename );
-
+            std::make_unique<JOB_EXPORT_SCH_PLOT>( true );
+    plotJob->m_filename = filename;
+    plotJob->m_plotFormat = m_plotFormat;
     plotJob->m_plotPages = pages;
     plotJob->m_plotDrawingSheet = !m_argParser.get<bool>( ARG_EXCLUDE_DRAWING_SHEET );
     plotJob->m_pageSizeSelect = JOB_PAGE_SIZE::PAGE_SIZE_AUTO;
diff --git a/kicad/cli/command_sch_export_pythonbom.cpp b/kicad/cli/command_sch_export_pythonbom.cpp
index af15a2c21a..364c442dad 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>( true );
 
     bomJob->m_filename = m_argInput;
-    bomJob->m_outputFile = m_argOutput;
+    bomJob->SetOutputPath( m_argOutput );
 
     if( !wxFile::Exists( bomJob->m_filename ) )
     {
diff --git a/kicad/dialogs/dialog_job_config_base.cpp b/kicad/dialogs/dialog_job_config_base.cpp
new file mode 100644
index 0000000000..0e2b3df5fc
--- /dev/null
+++ b/kicad/dialogs/dialog_job_config_base.cpp
@@ -0,0 +1,52 @@
+///////////////////////////////////////////////////////////////////////////
+// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
+// http://www.wxformbuilder.org/
+//
+// PLEASE DO *NOT* EDIT THIS FILE!
+///////////////////////////////////////////////////////////////////////////
+
+#include "dialog_job_config_base.h"
+
+///////////////////////////////////////////////////////////////////////////
+
+DIALOG_JOB_CONFIG_BASE::DIALOG_JOB_CONFIG_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( wxDefaultSize, wxDefaultSize );
+
+	m_mainSizer = new wxBoxSizer( wxVERTICAL );
+
+	m_staticText1 = new wxStaticText( this, wxID_ANY, wxT("Options"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_staticText1->Wrap( -1 );
+	m_mainSizer->Add( m_staticText1, 0, wxALL, 5 );
+
+	m_jobOptionsPanel = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
+	m_jobOptionsSizer = new wxFlexGridSizer( 0, 2, 0, 0 );
+	m_jobOptionsSizer->SetFlexibleDirection( wxBOTH );
+	m_jobOptionsSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
+
+
+	m_jobOptionsPanel->SetSizer( m_jobOptionsSizer );
+	m_jobOptionsPanel->Layout();
+	m_jobOptionsSizer->Fit( m_jobOptionsPanel );
+	m_mainSizer->Add( m_jobOptionsPanel, 1, wxEXPAND | wxALL, 5 );
+
+	m_sdbSizer1 = new wxStdDialogButtonSizer();
+	m_sdbSizer1Save = new wxButton( this, wxID_SAVE );
+	m_sdbSizer1->AddButton( m_sdbSizer1Save );
+	m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL );
+	m_sdbSizer1->AddButton( m_sdbSizer1Cancel );
+	m_sdbSizer1->Realize();
+
+	m_mainSizer->Add( m_sdbSizer1, 0, wxEXPAND, 5 );
+
+
+	this->SetSizer( m_mainSizer );
+	this->Layout();
+	m_mainSizer->Fit( this );
+
+	this->Centre( wxBOTH );
+}
+
+DIALOG_JOB_CONFIG_BASE::~DIALOG_JOB_CONFIG_BASE()
+{
+}
diff --git a/kicad/dialogs/dialog_job_config_base.fbp b/kicad/dialogs/dialog_job_config_base.fbp
new file mode 100644
index 0000000000..3b7faff7ec
--- /dev/null
+++ b/kicad/dialogs/dialog_job_config_base.fbp
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<wxFormBuilder_Project>
+  <FileVersion major="1" minor="18"/>
+  <object class="Project" expanded="true">
+    <property name="code_generation">C++</property>
+    <property name="cpp_class_decoration">; </property>
+    <property name="cpp_disconnect_events">1</property>
+    <property name="cpp_event_generation">connect</property>
+    <property name="cpp_help_provider">none</property>
+    <property name="cpp_namespace"></property>
+    <property name="cpp_precompiled_header"></property>
+    <property name="cpp_use_array_enum">0</property>
+    <property name="cpp_use_enum">0</property>
+    <property name="embedded_files_path">res</property>
+    <property name="encoding">UTF-8</property>
+    <property name="file">dialog_job_config_base</property>
+    <property name="first_id">1000</property>
+    <property name="internationalize">0</property>
+    <property name="lua_skip_events">1</property>
+    <property name="lua_ui_table">UI</property>
+    <property name="name">DIALOG_JOB_CONFIG_BASE</property>
+    <property name="path">.</property>
+    <property name="php_disconnect_events">0</property>
+    <property name="php_disconnect_mode">source_name</property>
+    <property name="php_skip_events">1</property>
+    <property name="python_disconnect_events">0</property>
+    <property name="python_disconnect_mode">source_name</property>
+    <property name="python_image_path_wrapper_function_name"></property>
+    <property name="python_indent_with_spaces"></property>
+    <property name="python_skip_events">1</property>
+    <property name="relative_path">1</property>
+    <property name="use_microsoft_bom">0</property>
+    <property name="use_native_eol">0</property>
+    <object class="Dialog" expanded="true">
+      <property name="aui_managed">0</property>
+      <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
+      <property name="bg"></property>
+      <property name="center">wxBOTH</property>
+      <property name="context_help"></property>
+      <property name="context_menu">1</property>
+      <property name="drag_accept_files">0</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"></property>
+      <property name="name">DIALOG_JOB_CONFIG_BASE</property>
+      <property name="pos"></property>
+      <property name="size"></property>
+      <property name="style">wxDEFAULT_DIALOG_STYLE</property>
+      <property name="subclass">DIALOG_SHIM; dialog_shim.h; forward_declare</property>
+      <property name="title"></property>
+      <property name="tooltip"></property>
+      <property name="two_step_creation">0</property>
+      <property name="window_extra_style"></property>
+      <property name="window_name"></property>
+      <property name="window_style"></property>
+      <object class="wxBoxSizer" expanded="true">
+        <property name="minimum_size"></property>
+        <property name="name">m_mainSizer</property>
+        <property name="orient">wxVERTICAL</property>
+        <property name="permission">protected</property>
+        <object class="sizeritem" expanded="true">
+          <property name="border">5</property>
+          <property name="flag">wxALL</property>
+          <property name="proportion">0</property>
+          <object class="wxStaticText" expanded="true">
+            <property name="BottomDockable">1</property>
+            <property name="LeftDockable">1</property>
+            <property name="RightDockable">1</property>
+            <property name="TopDockable">1</property>
+            <property name="aui_layer">0</property>
+            <property name="aui_name"></property>
+            <property name="aui_position">0</property>
+            <property name="aui_row">0</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="drag_accept_files">0</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">Options</property>
+            <property name="markup">0</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_staticText1</property>
+            <property name="pane_border">1</property>
+            <property name="pane_position"></property>
+            <property name="pane_size"></property>
+            <property name="permission">public</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"></property>
+            <property name="window_extra_style"></property>
+            <property name="window_name"></property>
+            <property name="window_style"></property>
+            <property name="wrap">-1</property>
+          </object>
+        </object>
+        <object class="sizeritem" expanded="true">
+          <property name="border">5</property>
+          <property name="flag">wxEXPAND | wxALL</property>
+          <property name="proportion">1</property>
+          <object class="wxPanel" expanded="true">
+            <property name="BottomDockable">1</property>
+            <property name="LeftDockable">1</property>
+            <property name="RightDockable">1</property>
+            <property name="TopDockable">1</property>
+            <property name="aui_layer">0</property>
+            <property name="aui_name"></property>
+            <property name="aui_position">0</property>
+            <property name="aui_row">0</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="drag_accept_files">0</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"></property>
+            <property name="moveable">1</property>
+            <property name="name">m_jobOptionsPanel</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">; ; forward_declare</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 class="wxFlexGridSizer" expanded="true">
+              <property name="cols">2</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">m_jobOptionsSizer</property>
+              <property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
+              <property name="permission">protected</property>
+              <property name="rows">0</property>
+              <property name="vgap">0</property>
+            </object>
+          </object>
+        </object>
+        <object class="sizeritem" expanded="true">
+          <property name="border">5</property>
+          <property name="flag">wxEXPAND</property>
+          <property name="proportion">0</property>
+          <object class="wxStdDialogButtonSizer" expanded="true">
+            <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">0</property>
+            <property name="Save">1</property>
+            <property name="Yes">0</property>
+            <property name="minimum_size"></property>
+            <property name="name">m_sdbSizer1</property>
+            <property name="permission">protected</property>
+          </object>
+        </object>
+      </object>
+    </object>
+  </object>
+</wxFormBuilder_Project>
diff --git a/kicad/dialogs/dialog_job_config_base.h b/kicad/dialogs/dialog_job_config_base.h
new file mode 100644
index 0000000000..7aea7b19e4
--- /dev/null
+++ b/kicad/dialogs/dialog_job_config_base.h
@@ -0,0 +1,49 @@
+///////////////////////////////////////////////////////////////////////////
+// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
+// http://www.wxformbuilder.org/
+//
+// PLEASE DO *NOT* EDIT THIS FILE!
+///////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include <wx/artprov.h>
+#include <wx/xrc/xmlres.h>
+#include "dialog_shim.h"
+#include <wx/string.h>
+#include <wx/stattext.h>
+#include <wx/gdicmn.h>
+#include <wx/font.h>
+#include <wx/colour.h>
+#include <wx/settings.h>
+#include <wx/sizer.h>
+#include <wx/panel.h>
+#include <wx/button.h>
+#include <wx/dialog.h>
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+/// Class DIALOG_JOB_CONFIG_BASE
+///////////////////////////////////////////////////////////////////////////////
+class DIALOG_JOB_CONFIG_BASE : public DIALOG_SHIM
+{
+	private:
+
+	protected:
+		wxBoxSizer* m_mainSizer;
+		wxPanel* m_jobOptionsPanel;
+		wxFlexGridSizer* m_jobOptionsSizer;
+		wxStdDialogButtonSizer* m_sdbSizer1;
+		wxButton* m_sdbSizer1Save;
+		wxButton* m_sdbSizer1Cancel;
+
+	public:
+		wxStaticText* m_staticText1;
+
+		DIALOG_JOB_CONFIG_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE );
+
+		~DIALOG_JOB_CONFIG_BASE();
+
+};
+
diff --git a/kicad/dialogs/panel_jobs.cpp b/kicad/dialogs/panel_jobs.cpp
new file mode 100644
index 0000000000..bf1a15c368
--- /dev/null
+++ b/kicad/dialogs/panel_jobs.cpp
@@ -0,0 +1,569 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "panel_jobs.h"
+#include <wx/aui/auibook.h>
+#include <jobs/jobset.h>
+#include <jobs/job_registry.h>
+#include <eda_list_dialog.h>
+#include <dialogs/dialog_job_config_base.h>
+#include <wx/checkbox.h>
+#include <wx/menu.h>
+#include <bitmaps.h>
+#include <i18n_utility.h>
+#include <jobs_runner.h>
+#include <widgets/wx_progress_reporters.h>
+#include <jobs/jobs_output_archive.h>
+#include <jobs/jobs_output_folder.h>
+#include <kicad_manager_frame.h>
+#include <vector>
+
+#include <wx/dirdlg.h>
+#include <wx/filedlg.h>
+#include <wildcards_and_files_ext.h>
+#include <widgets/std_bitmap_button.h>
+
+#include <confirm.h>
+
+
+struct JOB_TYPE_INFO
+{
+    wxString              name;
+    enum class BITMAPS    bitmap;
+    bool                  outputPathIsFolder;
+    wxString              fileWildcard;
+};
+
+
+static std::map<JOBSET_OUTPUT_TYPE, JOB_TYPE_INFO> jobTypeInfos = {
+    { JOBSET_OUTPUT_TYPE::FOLDER,
+        { _HKI( "Folder" ), BITMAPS::small_folder, true, "" } },
+    { JOBSET_OUTPUT_TYPE::ARCHIVE,
+        { _HKI( "Archive" ), BITMAPS::zip, false, FILEEXT::ZipFileWildcard() } },
+};
+
+
+class DIALOG_JOB_OUTPUT : public DIALOG_JOB_OUTPUT_BASE
+{
+public:
+    DIALOG_JOB_OUTPUT( wxWindow* aParent, JOBSET* aJobsFile, JOBSET_OUTPUT* aOutput ) :
+            DIALOG_JOB_OUTPUT_BASE( aParent ), m_jobsFile( aJobsFile ), m_output( aOutput )
+    {
+        SetAffirmativeId( wxID_SAVE );
+
+        if( m_output->m_type != JOBSET_OUTPUT_TYPE::ARCHIVE )
+        {
+            m_textArchiveFormat->Hide();
+            m_choiceArchiveformat->Hide();
+        }
+
+        m_buttonOutputPath->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
+    }
+
+
+    virtual void onOutputPathBrowseClicked(wxCommandEvent& event) override
+    {
+        bool isFolder = false;
+        wxString fileWildcard = "";
+        if( jobTypeInfos.contains( m_output->m_type ) )
+        {
+            isFolder = jobTypeInfos[m_output->m_type].outputPathIsFolder;
+            fileWildcard = jobTypeInfos[m_output->m_type].fileWildcard;
+        }
+
+        if( isFolder )
+        {
+            wxFileName fn;
+            fn.AssignDir( m_textCtrlOutputPath->GetValue() );
+            fn.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
+            wxString currPath = fn.GetFullPath();
+
+            wxDirDialog dirDialog( this, _( "Select Templates Directory" ), currPath,
+                                   wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST );
+
+            if( dirDialog.ShowModal() != wxID_OK )
+                return;
+
+            wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
+
+            m_textCtrlOutputPath->SetValue( dirName.GetFullPath() );
+        }
+        else
+        {
+            wxFileDialog dlg( this, _( "Select output path" ), m_textCtrlOutputPath->GetValue(),
+                              "test.zip",
+                              fileWildcard,
+                              wxFD_OVERWRITE_PROMPT | wxFD_SAVE );
+
+            if( dlg.ShowModal() != wxID_OK )
+            {
+                return;
+            }
+
+            wxFileName fname_log( dlg.GetPath() );
+        }
+
+    }
+
+    bool TransferDataFromWindow() override
+    {
+        wxArrayInt selectedItems;
+        m_listBoxOnly->GetSelections( selectedItems );
+
+        // Update the only job map
+        m_output->m_only.clear();
+        for( int i : selectedItems )
+        {
+            if( m_onlyMap.contains( i ) )
+            {
+                m_output->m_only.emplace_back( m_onlyMap[i] );
+            }
+        }
+
+        m_output->m_outputHandler->SetOutputPath( m_textCtrlOutputPath->GetValue() );
+
+        if( m_output->m_type == JOBSET_OUTPUT_TYPE::ARCHIVE )
+        {
+            JOBS_OUTPUT_ARCHIVE* archive =
+                    static_cast<JOBS_OUTPUT_ARCHIVE*>( m_output->m_outputHandler );
+
+            archive->SetFormat( JOBS_OUTPUT_ARCHIVE::FORMAT::ZIP );
+        }
+
+
+        return true;
+    }
+
+
+    bool TransferDataToWindow() override
+    {
+        wxArrayString arrayStr;
+        std::vector<int>    selectedList;
+
+        std::vector<JOBSET_JOB> jobs = m_jobsFile->GetJobs();
+        int                        i = 0;
+        for( JOBSET_JOB& job : jobs )
+        {
+            arrayStr.Add( job.m_job->GetDescription() );
+
+            auto it = std::find_if( m_output->m_only.begin(), m_output->m_only.end(),
+                                    [&]( const wxString& only )
+                                    {
+                                        if( only == job.m_id )
+                                            return true;
+
+                                        return false;
+                                    } );
+
+            if( it != m_output->m_only.end() )
+            {
+                selectedList.emplace_back( i );
+            }
+
+            m_onlyMap.emplace( i, job.m_id );
+            i++;
+        }
+
+        m_listBoxOnly->InsertItems( arrayStr, 0 );
+
+        for( int idx : selectedList )
+        {
+            m_listBoxOnly->SetSelection( idx );
+        }
+
+        m_choiceArchiveformat->AppendString( _( "Zip" ) );
+        m_choiceArchiveformat->SetSelection( 0 );
+
+        if( m_output->m_type == JOBSET_OUTPUT_TYPE::ARCHIVE )
+        {
+            JOBS_OUTPUT_ARCHIVE* archive = static_cast<JOBS_OUTPUT_ARCHIVE*>( m_output->m_outputHandler );
+        }
+        else
+        {
+            JOBS_OUTPUT_FOLDER* folder =
+                    static_cast<JOBS_OUTPUT_FOLDER*>( m_output->m_outputHandler );
+        }
+
+        return true;
+    }
+
+
+private:
+    JOBSET*        m_jobsFile;
+    JOBSET_OUTPUT* m_output;
+    std::map<int, wxString> m_onlyMap;
+};
+
+
+class PANEL_JOB_OUTPUT : public PANEL_JOB_OUTPUT_BASE
+{
+public:
+    PANEL_JOB_OUTPUT( wxWindow* aParent, PANEL_JOBS* aPanelParent, KICAD_MANAGER_FRAME* aFrame,
+                     JOBSET* aFile, JOBSET_OUTPUT* aOutput ) :
+            PANEL_JOB_OUTPUT_BASE( aParent ),
+            m_jobsFile( aFile ),
+            m_output( aOutput ),
+            m_frame( aFrame ),
+            m_panelParent( aPanelParent )
+    {
+        m_buttonOutputRun->SetBitmap( KiBitmapBundle( BITMAPS::sim_run ) );
+        m_buttonOutputOptions->SetBitmap( KiBitmapBundle( BITMAPS::preference ) );
+
+        m_buttonOutputOptions->Connect( wxEVT_MENU,
+                                        wxCommandEventHandler( PANEL_JOB_OUTPUT::onMenu ), nullptr, this );
+
+        if( jobTypeInfos.contains( aOutput->m_type ) )
+        {
+            JOB_TYPE_INFO& jobTypeInfo = jobTypeInfos[aOutput->m_type];
+            m_textOutputType->SetLabel( wxGetTranslation( jobTypeInfo.name ) );
+            m_bitmapOutputType->SetBitmap( KiBitmapBundle( jobTypeInfo.bitmap ) );
+        }
+    }
+
+
+    ~PANEL_JOB_OUTPUT()
+    {
+        m_buttonOutputOptions->Disconnect(
+                wxEVT_MENU, wxCommandEventHandler( PANEL_JOB_OUTPUT::onMenu ), nullptr, this );
+    }
+
+
+    virtual void OnOutputRunClick( wxCommandEvent& event ) override
+    {
+        CallAfter(
+                [this]()
+                {
+                    PROJECT&      project = m_frame->Kiway().Prj();
+                    m_panelParent->EnsurePcbSchFramesOpen();
+
+                    wxFileName fn = project.GetProjectFullName();
+                    wxSetWorkingDirectory( fn.GetPath() );
+
+                    JOBS_RUNNER jobRunner( &( m_frame->Kiway() ), m_jobsFile );
+
+                    WX_PROGRESS_REPORTER* progressReporter =
+                            new WX_PROGRESS_REPORTER( m_frame, _( "Running jobs" ), 1 );
+
+                    jobRunner.RunJobsForOutput( m_output );
+
+                    delete progressReporter;
+                } );
+    }
+
+    virtual void OnOutputOptionsClick( wxCommandEvent& event ) override
+    {
+        wxMenu menu;
+        menu.Append( wxID_EDIT, _( "Edit..." ) );
+        menu.Append( wxID_DELETE, _( "Delete" ) );
+
+        m_buttonOutputOptions->PopupMenu( &menu );
+    }
+
+
+private:
+    void onMenu( wxCommandEvent& aEvent )
+    {
+        switch( aEvent.GetId() )
+        {
+            case wxID_EDIT:
+            {
+                DIALOG_JOB_OUTPUT dialog( m_frame, m_jobsFile, m_output );
+
+                dialog.ShowModal();
+            }
+                break;
+
+            case wxID_DELETE:
+                m_panelParent->RemoveOutput( m_output );
+                break;
+
+            default:
+                wxFAIL_MSG( wxT( "Unknown ID in context menu event" ) );
+        }
+    }
+
+    JOBSET*           m_jobsFile;
+    JOBSET_OUTPUT*    m_output;
+    KICAD_MANAGER_FRAME* m_frame;
+    PANEL_JOBS*          m_panelParent;
+};
+
+
+PANEL_JOBS::PANEL_JOBS( wxAuiNotebook* aParent, KICAD_MANAGER_FRAME* aFrame,
+                        std::unique_ptr<JOBSET> aJobsFile ) :
+	PANEL_JOBS_BASE( aParent ),
+	m_parentBook( aParent ),
+    m_frame( aFrame ),
+	m_jobsFile( std::move( aJobsFile ) )
+{
+    int jobNoColId = m_jobList->AppendColumn( _( "No." ) );
+    int jobDescColId = m_jobList->AppendColumn( _( "Job Description" ) );
+    m_jobList->SetColumnWidth( jobNoColId, wxLIST_AUTOSIZE_USEHEADER );
+    m_jobList->SetColumnWidth( jobDescColId, wxLIST_AUTOSIZE_USEHEADER );
+
+    m_buttonAddJob->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
+    m_buttonUp->SetBitmap( KiBitmapBundle( BITMAPS::small_up ) );
+    m_buttonDown->SetBitmap( KiBitmapBundle( BITMAPS::small_down ) );
+    m_buttonOutputAdd->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
+
+    rebuildJobList();
+    buildOutputList();
+}
+
+
+void PANEL_JOBS::RemoveOutput( JOBSET_OUTPUT* aOutput )
+{
+    auto it = m_outputPanelMap.find( aOutput );
+    if( it != m_outputPanelMap.end() )
+    {
+        PANEL_JOB_OUTPUT* panel = m_outputPanelMap[aOutput];
+        m_outputListSizer->Detach( panel );
+        panel->Destroy();
+
+        m_outputPanelMap.erase( it );
+
+        // ensure the window contents get shifted as needed
+        m_outputList->Layout();
+        Layout();
+    }
+
+    m_jobsFile->RemoveOutput( aOutput );
+}
+
+
+void PANEL_JOBS::rebuildJobList()
+{
+    m_jobList->DeleteAllItems();
+
+    int num = 1;
+    for( auto& job : m_jobsFile->GetJobs() )
+    {
+        long itemIndex =
+                m_jobList->InsertItem( m_jobList->GetItemCount(), wxString::Format( "%d", num++ ) );
+        m_jobList->SetItem( itemIndex, 1, job.m_job->GetDescription() );
+    }
+
+    updateTitle();
+}
+
+
+void PANEL_JOBS::updateTitle()
+{
+    wxString tabName = m_jobsFile->GetFullName();
+    if( m_jobsFile->GetDirty() )
+    {
+        tabName = wxS( "*" ) + tabName;
+    }
+    int pageIdx = m_parentBook->FindPage( this );
+    m_parentBook->SetPageText( pageIdx, tabName );
+}
+
+
+void PANEL_JOBS::addJobOutputPanel( JOBSET_OUTPUT* aOutput )
+{
+    PANEL_JOB_OUTPUT* outputPanel =
+            new PANEL_JOB_OUTPUT( m_outputList, this, m_frame, m_jobsFile.get(), aOutput );
+    m_outputListSizer->Add( outputPanel, 0, wxEXPAND | wxALL, 5 );
+
+    m_outputPanelMap[aOutput] = outputPanel;
+
+    m_outputList->Layout();
+}
+
+
+void PANEL_JOBS::buildOutputList()
+{
+    Freeze();
+    m_outputPanelMap.clear();
+
+    for( auto& job : m_jobsFile->GetOutputs() )
+    {
+        addJobOutputPanel( &job );
+    }
+
+    // ensure the window contents get shifted as needed
+    Layout();
+    Thaw();
+}
+
+
+void PANEL_JOBS::OnJobListDoubleClicked( wxListEvent& aEvent )
+{
+    EnsurePcbSchFramesOpen();
+
+    long               item = aEvent.GetIndex();
+
+    JOBSET_JOB& job = m_jobsFile->GetJobs()[item];
+
+    KIWAY::FACE_T iface = JOB_REGISTRY::GetKifaceType( job.m_type );
+
+    int result = m_frame->Kiway().ProcessJobConfigDialog( iface, job.m_job, m_frame );
+}
+
+
+void PANEL_JOBS::OnSaveButtonClick( wxCommandEvent& aEvent )
+{
+    m_jobsFile->SaveToFile();
+    updateTitle();
+}
+
+
+void PANEL_JOBS::OnAddJobClick( wxCommandEvent& aEvent )
+{
+    wxArrayString              headers;
+    std::vector<wxArrayString> items;
+
+    headers.Add( _( "Job Types" ) );
+
+    const JOB_REGISTRY::REGISTRY_MAP_T& jobMap =  JOB_REGISTRY::GetRegistry();
+
+    for( const std::pair<wxString, JOB_REGISTRY_ENTRY>& entry : jobMap )
+    {
+        wxArrayString item;
+        item.Add( wxGetTranslation( entry.second.title ) );
+        items.emplace_back( item );
+    }
+
+    EDA_LIST_DIALOG dlg( this, _( "Add New Job" ), headers, items );
+    dlg.SetListLabel( _( "Select job type:" ) );
+
+    if( dlg.ShowModal() == wxID_OK )
+    {
+        wxString selectedString = dlg.GetTextSelection();
+
+        wxString jobKey;
+        if( !selectedString.IsEmpty() )
+        {
+            for( const std::pair<wxString, JOB_REGISTRY_ENTRY>& entry : jobMap )
+            {
+                if( wxGetTranslation( entry.second.title ) == selectedString )
+                {
+                    jobKey = entry.first;
+                    break;
+                }
+            }
+        }
+
+        if( !jobKey.IsEmpty() )
+        {
+            JOB* job = JOB_REGISTRY::CreateInstance<JOB>( jobKey );
+            m_jobsFile->AddNewJob( jobKey, job );
+
+            rebuildJobList();
+        }
+    }
+}
+
+
+void PANEL_JOBS::OnAddOutputClick( wxCommandEvent& aEvent )
+{
+    wxArrayString              headers;
+    std::vector<wxArrayString> items;
+
+    headers.Add( _( "Job Types" ) );
+
+    for( const std::pair<JOBSET_OUTPUT_TYPE, JOB_TYPE_INFO>& jobType : jobTypeInfos )
+    {
+        wxArrayString item;
+        item.Add( wxGetTranslation( jobType.second.name ) );
+        items.emplace_back( item );
+    }
+
+    EDA_LIST_DIALOG dlg( this, _( "Add New Output" ), headers, items );
+    dlg.SetListLabel( _( "Select output type:" ) );
+    dlg.HideFilter();
+
+    if( dlg.ShowModal() == wxID_OK )
+    {
+        wxString selectedString = dlg.GetTextSelection();
+
+        for( const std::pair<JOBSET_OUTPUT_TYPE, JOB_TYPE_INFO>& jobType : jobTypeInfos )
+        {
+            if( wxGetTranslation( jobType.second.name ) == selectedString )
+            {
+                JOBSET_OUTPUT output = m_jobsFile->AddNewJobOutput( jobType.first, nullptr );
+
+                Freeze();
+                addJobOutputPanel( &output );
+                Thaw();
+            }
+        }
+    }
+}
+
+
+bool PANEL_JOBS::GetCanClose()
+{
+    if( m_jobsFile->GetDirty() )
+    {
+        wxFileName fileName = m_jobsFile->GetFullFilename();
+        wxString   msg = _( "Save changes to '%s' before closing?" );
+
+        if( !HandleUnsavedChanges( this, wxString::Format( msg, fileName.GetFullName() ),
+                                   [&]() -> bool
+                                   {
+                                        return m_jobsFile->SaveToFile();
+                                   } ) )
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+
+void PANEL_JOBS::EnsurePcbSchFramesOpen()
+{
+    PROJECT&      project = m_frame->Kiway().Prj();
+    KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_PCB_EDITOR, false );
+
+    if( !frame )
+    {
+        frame = m_frame->Kiway().Player( FRAME_PCB_EDITOR, true );
+
+        // frame can be null if Cvpcb cannot be run. No need to show a warning
+        // Kiway() generates the error messages
+        if( !frame )
+            return;
+
+        wxFileName boardfn = project.GetProjectFullName();
+        boardfn.SetExt( FILEEXT::PcbFileExtension );
+
+        frame->OpenProjectFiles( std::vector<wxString>( 1, boardfn.GetFullPath() ) );
+    }
+
+    frame = m_frame->Kiway().Player( FRAME_SCH, false );
+
+    if( !frame )
+    {
+        frame = m_frame->Kiway().Player( FRAME_SCH, true );
+
+        // frame can be null if Cvpcb cannot be run. No need to show a warning
+        // Kiway() generates the error messages
+        if( !frame )
+            return;
+
+        wxFileName schFn = project.GetProjectFullName();
+        schFn.SetExt( FILEEXT::KiCadSchematicFileExtension );
+
+        frame->OpenProjectFiles( std::vector<wxString>( 1, schFn.GetFullPath() ) );
+    }
+}
\ No newline at end of file
diff --git a/kicad/dialogs/panel_jobs.h b/kicad/dialogs/panel_jobs.h
new file mode 100644
index 0000000000..5d60720ad4
--- /dev/null
+++ b/kicad/dialogs/panel_jobs.h
@@ -0,0 +1,61 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "panel_jobs_base.h"
+#include <memory>
+
+class wxAuiNotebook;
+class JOBSET;
+class KICAD_MANAGER_FRAME;
+class PANEL_JOB_OUTPUT;
+struct JOBSET_OUTPUT;
+
+class PANEL_JOBS : public PANEL_JOBS_BASE
+{
+public:
+    PANEL_JOBS( wxAuiNotebook* aParent, KICAD_MANAGER_FRAME* aFrame,
+                std::unique_ptr<JOBSET> aJobsFile );
+
+    void RemoveOutput( JOBSET_OUTPUT* aOutput );
+
+    void EnsurePcbSchFramesOpen();
+
+protected:
+    virtual void OnAddJobClick( wxCommandEvent& aEvent ) override;
+    virtual void OnAddOutputClick( wxCommandEvent& aEvent ) override;
+    virtual void OnJobListDoubleClicked( wxListEvent& aEvent ) override;
+    virtual void OnSaveButtonClick( wxCommandEvent& aEvent ) override;
+
+    bool GetCanClose() override;
+
+private:
+    void rebuildJobList();
+    void updateTitle();
+    void buildOutputList();
+    void addJobOutputPanel( JOBSET_OUTPUT* aOutput );
+
+    wxAuiNotebook*             m_parentBook;
+    KICAD_MANAGER_FRAME*       m_frame;
+    std::unique_ptr<JOBSET> m_jobsFile;
+
+    std::unordered_map<JOBSET_OUTPUT*, PANEL_JOB_OUTPUT*> m_outputPanelMap;
+};
\ No newline at end of file
diff --git a/kicad/dialogs/panel_jobs_base.cpp b/kicad/dialogs/panel_jobs_base.cpp
new file mode 100644
index 0000000000..a7a94dbe0e
--- /dev/null
+++ b/kicad/dialogs/panel_jobs_base.cpp
@@ -0,0 +1,249 @@
+///////////////////////////////////////////////////////////////////////////
+// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
+// http://www.wxformbuilder.org/
+//
+// PLEASE DO *NOT* EDIT THIS FILE!
+///////////////////////////////////////////////////////////////////////////
+
+#include "widgets/std_bitmap_button.h"
+
+#include "panel_jobs_base.h"
+
+///////////////////////////////////////////////////////////////////////////
+
+PANEL_JOBS_BASE::PANEL_JOBS_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : PANEL_NOTEBOOK_BASE( parent, id, pos, size, style, name )
+{
+	wxBoxSizer* bSizer1;
+	bSizer1 = new wxBoxSizer( wxHORIZONTAL );
+
+	wxBoxSizer* bSizer3;
+	bSizer3 = new wxBoxSizer( wxVERTICAL );
+
+	m_staticText1 = new wxStaticText( this, wxID_ANY, wxT("Jobs"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_staticText1->Wrap( -1 );
+	bSizer3->Add( m_staticText1, 0, wxALL, 5 );
+
+	m_jobList = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxLC_SINGLE_SEL );
+	bSizer3->Add( m_jobList, 1, wxALL|wxBOTTOM|wxEXPAND|wxLEFT|wxTOP, 5 );
+
+	wxBoxSizer* bSizer2;
+	bSizer2 = new wxBoxSizer( wxHORIZONTAL );
+
+	m_buttonAddJob = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
+	bSizer2->Add( m_buttonAddJob, 0, wxALIGN_CENTER|wxALL, 5 );
+
+	m_buttonUp = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
+	bSizer2->Add( m_buttonUp, 0, wxALL, 5 );
+
+	m_buttonDown = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
+	bSizer2->Add( m_buttonDown, 0, wxALL, 5 );
+
+
+	bSizer2->Add( 0, 0, 1, wxEXPAND, 5 );
+
+	m_buttonSave = new wxButton( this, wxID_ANY, wxT("Save"), wxDefaultPosition, wxDefaultSize, 0 );
+	bSizer2->Add( m_buttonSave, 0, wxALIGN_CENTER|wxALL, 5 );
+
+
+	bSizer3->Add( bSizer2, 0, wxEXPAND, 5 );
+
+
+	bSizer1->Add( bSizer3, 2, wxEXPAND, 5 );
+
+	wxBoxSizer* bSizer4;
+	bSizer4 = new wxBoxSizer( wxVERTICAL );
+
+	wxBoxSizer* bSizer14;
+	bSizer14 = new wxBoxSizer( wxHORIZONTAL );
+
+	m_staticText4 = new wxStaticText( this, wxID_ANY, wxT("Outputs"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_staticText4->Wrap( -1 );
+	bSizer14->Add( m_staticText4, 0, wxALL, 5 );
+
+	m_buttonOutputAdd = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
+	bSizer14->Add( m_buttonOutputAdd, 0, 0, 5 );
+
+
+	bSizer4->Add( bSizer14, 0, wxEXPAND, 5 );
+
+	m_outputList = new wxScrolledWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL );
+	m_outputList->SetScrollRate( 5, 5 );
+	m_outputListSizer = new wxBoxSizer( wxVERTICAL );
+
+
+	m_outputList->SetSizer( m_outputListSizer );
+	m_outputList->Layout();
+	m_outputListSizer->Fit( m_outputList );
+	bSizer4->Add( m_outputList, 1, wxEXPAND | wxALL, 0 );
+
+	m_buttonRunAllOutputs = new wxButton( this, wxID_ANY, wxT("Run All Jobs"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_buttonRunAllOutputs->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
+
+	bSizer4->Add( m_buttonRunAllOutputs, 0, wxALIGN_RIGHT|wxALL, 5 );
+
+
+	bSizer1->Add( bSizer4, 1, wxEXPAND, 5 );
+
+
+	this->SetSizer( bSizer1 );
+	this->Layout();
+
+	// Connect Events
+	m_jobList->Connect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( PANEL_JOBS_BASE::OnJobListDoubleClicked ), NULL, this );
+	m_jobList->Connect( wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, wxListEventHandler( PANEL_JOBS_BASE::OnJobListItemRightClick ), NULL, this );
+	m_buttonAddJob->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_JOBS_BASE::OnAddJobClick ), NULL, this );
+	m_buttonSave->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_JOBS_BASE::OnSaveButtonClick ), NULL, this );
+	m_buttonOutputAdd->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_JOBS_BASE::OnAddOutputClick ), NULL, this );
+	m_buttonRunAllOutputs->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_JOBS_BASE::OnRunAllJobsClick ), NULL, this );
+}
+
+PANEL_JOBS_BASE::~PANEL_JOBS_BASE()
+{
+	// Disconnect Events
+	m_jobList->Disconnect( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler( PANEL_JOBS_BASE::OnJobListDoubleClicked ), NULL, this );
+	m_jobList->Disconnect( wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, wxListEventHandler( PANEL_JOBS_BASE::OnJobListItemRightClick ), NULL, this );
+	m_buttonAddJob->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_JOBS_BASE::OnAddJobClick ), NULL, this );
+	m_buttonSave->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_JOBS_BASE::OnSaveButtonClick ), NULL, this );
+	m_buttonOutputAdd->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_JOBS_BASE::OnAddOutputClick ), NULL, this );
+	m_buttonRunAllOutputs->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_JOBS_BASE::OnRunAllJobsClick ), NULL, this );
+
+}
+
+PANEL_JOB_OUTPUT_BASE::PANEL_JOB_OUTPUT_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
+{
+	this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT ) );
+
+	wxBoxSizer* bSizer11;
+	bSizer11 = new wxBoxSizer( wxHORIZONTAL );
+
+	m_bitmapOutputType = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
+	bSizer11->Add( m_bitmapOutputType, 0, wxALL, 5 );
+
+	wxBoxSizer* bSizer12;
+	bSizer12 = new wxBoxSizer( wxVERTICAL );
+
+	m_textOutputType = new wxStaticText( this, wxID_ANY, wxT("Placeholder"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_textOutputType->Wrap( -1 );
+	m_textOutputType->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
+
+	bSizer12->Add( m_textOutputType, 0, wxALL, 5 );
+
+
+	bSizer11->Add( bSizer12, 1, wxEXPAND, 5 );
+
+	wxBoxSizer* bSizer13;
+	bSizer13 = new wxBoxSizer( wxVERTICAL );
+
+	m_buttonOutputRun = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
+	bSizer13->Add( m_buttonOutputRun, 0, wxALL, 5 );
+
+	m_buttonOutputOptions = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
+	bSizer13->Add( m_buttonOutputOptions, 0, wxALL, 5 );
+
+
+	bSizer11->Add( bSizer13, 0, wxEXPAND, 5 );
+
+
+	this->SetSizer( bSizer11 );
+	this->Layout();
+	bSizer11->Fit( this );
+
+	// Connect Events
+	m_buttonOutputRun->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_JOB_OUTPUT_BASE::OnOutputRunClick ), NULL, this );
+	m_buttonOutputOptions->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_JOB_OUTPUT_BASE::OnOutputOptionsClick ), NULL, this );
+}
+
+PANEL_JOB_OUTPUT_BASE::~PANEL_JOB_OUTPUT_BASE()
+{
+	// Disconnect Events
+	m_buttonOutputRun->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_JOB_OUTPUT_BASE::OnOutputRunClick ), NULL, this );
+	m_buttonOutputOptions->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_JOB_OUTPUT_BASE::OnOutputOptionsClick ), NULL, this );
+
+}
+
+DIALOG_JOB_OUTPUT_BASE::DIALOG_JOB_OUTPUT_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( wxDefaultSize, wxDefaultSize );
+
+	wxBoxSizer* bSizer15;
+	bSizer15 = new wxBoxSizer( wxVERTICAL );
+
+	m_staticText9 = new wxStaticText( this, wxID_ANY, wxT("Options"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_staticText9->Wrap( -1 );
+	m_staticText9->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
+
+	bSizer15->Add( m_staticText9, 0, wxALL, 5 );
+
+	m_panel9 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
+	wxFlexGridSizer* fgSizer1;
+	fgSizer1 = new wxFlexGridSizer( 0, 2, 0, 0 );
+	fgSizer1->SetFlexibleDirection( wxBOTH );
+	fgSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
+
+	m_textArchiveFormat = new wxStaticText( m_panel9, wxID_ANY, wxT("Format"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_textArchiveFormat->Wrap( -1 );
+	fgSizer1->Add( m_textArchiveFormat, 0, wxALL, 5 );
+
+	wxArrayString m_choiceArchiveformatChoices;
+	m_choiceArchiveformat = new wxChoice( m_panel9, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choiceArchiveformatChoices, 0 );
+	m_choiceArchiveformat->SetSelection( 0 );
+	fgSizer1->Add( m_choiceArchiveformat, 0, wxALL, 5 );
+
+	m_textOutputPath = new wxStaticText( m_panel9, wxID_ANY, wxT("Output Path"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_textOutputPath->Wrap( -1 );
+	fgSizer1->Add( m_textOutputPath, 0, wxALL, 5 );
+
+	wxBoxSizer* bSizer16;
+	bSizer16 = new wxBoxSizer( wxHORIZONTAL );
+
+	m_textCtrlOutputPath = new wxTextCtrl( m_panel9, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+	m_textCtrlOutputPath->SetMinSize( wxSize( 350,-1 ) );
+
+	bSizer16->Add( m_textCtrlOutputPath, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
+
+	m_buttonOutputPath = new STD_BITMAP_BUTTON( m_panel9, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
+	bSizer16->Add( m_buttonOutputPath, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
+
+
+	fgSizer1->Add( bSizer16, 1, wxEXPAND, 5 );
+
+	m_staticText10 = new wxStaticText( m_panel9, wxID_ANY, wxT("Only Jobs"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_staticText10->Wrap( -1 );
+	fgSizer1->Add( m_staticText10, 0, wxALL, 5 );
+
+	m_listBoxOnly = new wxListBox( m_panel9, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_ALWAYS_SB|wxLB_MULTIPLE );
+	m_listBoxOnly->SetMinSize( wxSize( 300,200 ) );
+
+	fgSizer1->Add( m_listBoxOnly, 0, wxALL, 5 );
+
+
+	m_panel9->SetSizer( fgSizer1 );
+	m_panel9->Layout();
+	fgSizer1->Fit( m_panel9 );
+	bSizer15->Add( m_panel9, 1, wxEXPAND | wxALL, 5 );
+
+	m_sdbSizer1 = new wxStdDialogButtonSizer();
+	m_sdbSizer1Save = new wxButton( this, wxID_SAVE );
+	m_sdbSizer1->AddButton( m_sdbSizer1Save );
+	m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL );
+	m_sdbSizer1->AddButton( m_sdbSizer1Cancel );
+	m_sdbSizer1->Realize();
+
+	bSizer15->Add( m_sdbSizer1, 0, wxEXPAND, 5 );
+
+
+	this->SetSizer( bSizer15 );
+	this->Layout();
+
+	this->Centre( wxBOTH );
+
+	// Connect Events
+	m_buttonOutputPath->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_JOB_OUTPUT_BASE::onOutputPathBrowseClicked ), NULL, this );
+}
+
+DIALOG_JOB_OUTPUT_BASE::~DIALOG_JOB_OUTPUT_BASE()
+{
+	// Disconnect Events
+	m_buttonOutputPath->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_JOB_OUTPUT_BASE::onOutputPathBrowseClicked ), NULL, this );
+
+}
diff --git a/kicad/dialogs/panel_jobs_base.fbp b/kicad/dialogs/panel_jobs_base.fbp
new file mode 100644
index 0000000000..81ade8b07f
--- /dev/null
+++ b/kicad/dialogs/panel_jobs_base.fbp
@@ -0,0 +1,1799 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<wxFormBuilder_Project>
+  <FileVersion major="1" minor="18"/>
+  <object class="Project" expanded="true">
+    <property name="code_generation">C++</property>
+    <property name="cpp_class_decoration">; </property>
+    <property name="cpp_disconnect_events">1</property>
+    <property name="cpp_event_generation">connect</property>
+    <property name="cpp_help_provider">none</property>
+    <property name="cpp_namespace"></property>
+    <property name="cpp_precompiled_header"></property>
+    <property name="cpp_use_array_enum">0</property>
+    <property name="cpp_use_enum">0</property>
+    <property name="embedded_files_path">res</property>
+    <property name="encoding">UTF-8</property>
+    <property name="file">panel_jobs_base</property>
+    <property name="first_id">1000</property>
+    <property name="internationalize">0</property>
+    <property name="lua_skip_events">1</property>
+    <property name="lua_ui_table">UI</property>
+    <property name="name">PANEL_JOBS_BASE</property>
+    <property name="path">.</property>
+    <property name="php_disconnect_events">0</property>
+    <property name="php_disconnect_mode">source_name</property>
+    <property name="php_skip_events">1</property>
+    <property name="python_disconnect_events">0</property>
+    <property name="python_disconnect_mode">source_name</property>
+    <property name="python_image_path_wrapper_function_name"></property>
+    <property name="python_indent_with_spaces"></property>
+    <property name="python_skip_events">1</property>
+    <property name="relative_path">1</property>
+    <property name="use_microsoft_bom">0</property>
+    <property name="use_native_eol">0</property>
+    <object class="Panel" expanded="true">
+      <property name="aui_managed">0</property>
+      <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
+      <property name="bg"></property>
+      <property name="context_help"></property>
+      <property name="context_menu">1</property>
+      <property name="drag_accept_files">0</property>
+      <property name="enabled">1</property>
+      <property name="event_handler">impl_virtual</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"></property>
+      <property name="name">PANEL_JOBS_BASE</property>
+      <property name="pos"></property>
+      <property name="size">600,400</property>
+      <property name="subclass">PANEL_NOTEBOOK_BASE; dialogs/panel_notebook_base.h; forward_declare</property>
+      <property name="tooltip"></property>
+      <property name="two_step_creation">0</property>
+      <property name="window_extra_style"></property>
+      <property name="window_name"></property>
+      <property name="window_style">wxTAB_TRAVERSAL</property>
+      <object class="wxBoxSizer" expanded="true">
+        <property name="minimum_size"></property>
+        <property name="name">bSizer1</property>
+        <property name="orient">wxHORIZONTAL</property>
+        <property name="permission">none</property>
+        <object class="sizeritem" expanded="false">
+          <property name="border">5</property>
+          <property name="flag">wxEXPAND</property>
+          <property name="proportion">2</property>
+          <object class="wxBoxSizer" expanded="false">
+            <property name="minimum_size"></property>
+            <property name="name">bSizer3</property>
+            <property name="orient">wxVERTICAL</property>
+            <property name="permission">none</property>
+            <object class="sizeritem" expanded="false">
+              <property name="border">5</property>
+              <property name="flag">wxALL</property>
+              <property name="proportion">0</property>
+              <object class="wxStaticText" expanded="false">
+                <property name="BottomDockable">1</property>
+                <property name="LeftDockable">1</property>
+                <property name="RightDockable">1</property>
+                <property name="TopDockable">1</property>
+                <property name="aui_layer">0</property>
+                <property name="aui_name"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</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="drag_accept_files">0</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">Jobs</property>
+                <property name="markup">0</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_staticText1</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"></property>
+                <property name="window_extra_style"></property>
+                <property name="window_name"></property>
+                <property name="window_style"></property>
+                <property name="wrap">-1</property>
+              </object>
+            </object>
+            <object class="sizeritem" expanded="false">
+              <property name="border">5</property>
+              <property name="flag">wxALL|wxBOTTOM|wxEXPAND|wxLEFT|wxTOP</property>
+              <property name="proportion">1</property>
+              <object class="wxListCtrl" expanded="false">
+                <property name="BottomDockable">1</property>
+                <property name="LeftDockable">1</property>
+                <property name="RightDockable">1</property>
+                <property name="TopDockable">1</property>
+                <property name="aui_layer">0</property>
+                <property name="aui_name"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</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="drag_accept_files">0</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"></property>
+                <property name="moveable">1</property>
+                <property name="name">m_jobList</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">wxLC_REPORT|wxLC_SINGLE_SEL</property>
+                <property name="subclass">; ; forward_declare</property>
+                <property name="toolbar_pane">0</property>
+                <property name="tooltip"></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="OnListItemActivated">OnJobListDoubleClicked</event>
+                <event name="OnListItemRightClick">OnJobListItemRightClick</event>
+              </object>
+            </object>
+            <object class="sizeritem" expanded="false">
+              <property name="border">5</property>
+              <property name="flag">wxEXPAND</property>
+              <property name="proportion">0</property>
+              <object class="wxBoxSizer" expanded="false">
+                <property name="minimum_size"></property>
+                <property name="name">bSizer2</property>
+                <property name="orient">wxHORIZONTAL</property>
+                <property name="permission">none</property>
+                <object class="sizeritem" expanded="true">
+                  <property name="border">5</property>
+                  <property name="flag">wxALIGN_CENTER|wxALL</property>
+                  <property name="proportion">0</property>
+                  <object class="wxBitmapButton" expanded="true">
+                    <property name="BottomDockable">1</property>
+                    <property name="LeftDockable">1</property>
+                    <property name="RightDockable">1</property>
+                    <property name="TopDockable">1</property>
+                    <property name="aui_layer">0</property>
+                    <property name="aui_name"></property>
+                    <property name="aui_position">0</property>
+                    <property name="aui_row">0</property>
+                    <property name="auth_needed">0</property>
+                    <property name="best_size"></property>
+                    <property name="bg"></property>
+                    <property name="bitmap"></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="current"></property>
+                    <property name="default">0</property>
+                    <property name="default_pane">0</property>
+                    <property name="disabled"></property>
+                    <property name="dock">Dock</property>
+                    <property name="dock_fixed">0</property>
+                    <property name="docking">Left</property>
+                    <property name="drag_accept_files">0</property>
+                    <property name="enabled">1</property>
+                    <property name="fg"></property>
+                    <property name="floatable">1</property>
+                    <property name="focus"></property>
+                    <property name="font"></property>
+                    <property name="gripper">0</property>
+                    <property name="hidden">0</property>
+                    <property name="id">wxID_ANY</property>
+                    <property name="label">MyButton</property>
+                    <property name="margins"></property>
+                    <property name="markup">0</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_buttonAddJob</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="position"></property>
+                    <property name="pressed"></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"></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="OnButtonClick">OnAddJobClick</event>
+                  </object>
+                </object>
+                <object class="sizeritem" expanded="true">
+                  <property name="border">5</property>
+                  <property name="flag">wxALL</property>
+                  <property name="proportion">0</property>
+                  <object class="wxBitmapButton" expanded="true">
+                    <property name="BottomDockable">1</property>
+                    <property name="LeftDockable">1</property>
+                    <property name="RightDockable">1</property>
+                    <property name="TopDockable">1</property>
+                    <property name="aui_layer">0</property>
+                    <property name="aui_name"></property>
+                    <property name="aui_position">0</property>
+                    <property name="aui_row">0</property>
+                    <property name="auth_needed">0</property>
+                    <property name="best_size"></property>
+                    <property name="bg"></property>
+                    <property name="bitmap"></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="current"></property>
+                    <property name="default">0</property>
+                    <property name="default_pane">0</property>
+                    <property name="disabled"></property>
+                    <property name="dock">Dock</property>
+                    <property name="dock_fixed">0</property>
+                    <property name="docking">Left</property>
+                    <property name="drag_accept_files">0</property>
+                    <property name="enabled">1</property>
+                    <property name="fg"></property>
+                    <property name="floatable">1</property>
+                    <property name="focus"></property>
+                    <property name="font"></property>
+                    <property name="gripper">0</property>
+                    <property name="hidden">0</property>
+                    <property name="id">wxID_ANY</property>
+                    <property name="label">MyButton</property>
+                    <property name="margins"></property>
+                    <property name="markup">0</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_buttonUp</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="position"></property>
+                    <property name="pressed"></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"></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>
+                  </object>
+                </object>
+                <object class="sizeritem" expanded="true">
+                  <property name="border">5</property>
+                  <property name="flag">wxALL</property>
+                  <property name="proportion">0</property>
+                  <object class="wxBitmapButton" expanded="true">
+                    <property name="BottomDockable">1</property>
+                    <property name="LeftDockable">1</property>
+                    <property name="RightDockable">1</property>
+                    <property name="TopDockable">1</property>
+                    <property name="aui_layer">0</property>
+                    <property name="aui_name"></property>
+                    <property name="aui_position">0</property>
+                    <property name="aui_row">0</property>
+                    <property name="auth_needed">0</property>
+                    <property name="best_size"></property>
+                    <property name="bg"></property>
+                    <property name="bitmap"></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="current"></property>
+                    <property name="default">0</property>
+                    <property name="default_pane">0</property>
+                    <property name="disabled"></property>
+                    <property name="dock">Dock</property>
+                    <property name="dock_fixed">0</property>
+                    <property name="docking">Left</property>
+                    <property name="drag_accept_files">0</property>
+                    <property name="enabled">1</property>
+                    <property name="fg"></property>
+                    <property name="floatable">1</property>
+                    <property name="focus"></property>
+                    <property name="font"></property>
+                    <property name="gripper">0</property>
+                    <property name="hidden">0</property>
+                    <property name="id">wxID_ANY</property>
+                    <property name="label">MyButton</property>
+                    <property name="margins"></property>
+                    <property name="markup">0</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_buttonDown</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="position"></property>
+                    <property name="pressed"></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"></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>
+                  </object>
+                </object>
+                <object class="sizeritem" expanded="false">
+                  <property name="border">5</property>
+                  <property name="flag">wxEXPAND</property>
+                  <property name="proportion">1</property>
+                  <object class="spacer" expanded="false">
+                    <property name="height">0</property>
+                    <property name="permission">protected</property>
+                    <property name="width">0</property>
+                  </object>
+                </object>
+                <object class="sizeritem" expanded="false">
+                  <property name="border">5</property>
+                  <property name="flag">wxALIGN_CENTER|wxALL</property>
+                  <property name="proportion">0</property>
+                  <object class="wxButton" expanded="false">
+                    <property name="BottomDockable">1</property>
+                    <property name="LeftDockable">1</property>
+                    <property name="RightDockable">1</property>
+                    <property name="TopDockable">1</property>
+                    <property name="aui_layer">0</property>
+                    <property name="aui_name"></property>
+                    <property name="aui_position">0</property>
+                    <property name="aui_row">0</property>
+                    <property name="auth_needed">0</property>
+                    <property name="best_size"></property>
+                    <property name="bg"></property>
+                    <property name="bitmap"></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="current"></property>
+                    <property name="default">0</property>
+                    <property name="default_pane">0</property>
+                    <property name="disabled"></property>
+                    <property name="dock">Dock</property>
+                    <property name="dock_fixed">0</property>
+                    <property name="docking">Left</property>
+                    <property name="drag_accept_files">0</property>
+                    <property name="enabled">1</property>
+                    <property name="fg"></property>
+                    <property name="floatable">1</property>
+                    <property name="focus"></property>
+                    <property name="font"></property>
+                    <property name="gripper">0</property>
+                    <property name="hidden">0</property>
+                    <property name="id">wxID_ANY</property>
+                    <property name="label">Save</property>
+                    <property name="margins"></property>
+                    <property name="markup">0</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_buttonSave</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="position"></property>
+                    <property name="pressed"></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"></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="OnButtonClick">OnSaveButtonClick</event>
+                  </object>
+                </object>
+              </object>
+            </object>
+          </object>
+        </object>
+        <object class="sizeritem" expanded="true">
+          <property name="border">5</property>
+          <property name="flag">wxEXPAND</property>
+          <property name="proportion">1</property>
+          <object class="wxBoxSizer" expanded="true">
+            <property name="minimum_size"></property>
+            <property name="name">bSizer4</property>
+            <property name="orient">wxVERTICAL</property>
+            <property name="permission">none</property>
+            <object class="sizeritem" expanded="true">
+              <property name="border">5</property>
+              <property name="flag">wxEXPAND</property>
+              <property name="proportion">0</property>
+              <object class="wxBoxSizer" expanded="true">
+                <property name="minimum_size"></property>
+                <property name="name">bSizer14</property>
+                <property name="orient">wxHORIZONTAL</property>
+                <property name="permission">none</property>
+                <object class="sizeritem" expanded="false">
+                  <property name="border">5</property>
+                  <property name="flag">wxALL</property>
+                  <property name="proportion">0</property>
+                  <object class="wxStaticText" expanded="false">
+                    <property name="BottomDockable">1</property>
+                    <property name="LeftDockable">1</property>
+                    <property name="RightDockable">1</property>
+                    <property name="TopDockable">1</property>
+                    <property name="aui_layer">0</property>
+                    <property name="aui_name"></property>
+                    <property name="aui_position">0</property>
+                    <property name="aui_row">0</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="drag_accept_files">0</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">Outputs</property>
+                    <property name="markup">0</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_staticText4</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"></property>
+                    <property name="window_extra_style"></property>
+                    <property name="window_name"></property>
+                    <property name="window_style"></property>
+                    <property name="wrap">-1</property>
+                  </object>
+                </object>
+                <object class="sizeritem" expanded="true">
+                  <property name="border">5</property>
+                  <property name="flag"></property>
+                  <property name="proportion">0</property>
+                  <object class="wxBitmapButton" expanded="true">
+                    <property name="BottomDockable">1</property>
+                    <property name="LeftDockable">1</property>
+                    <property name="RightDockable">1</property>
+                    <property name="TopDockable">1</property>
+                    <property name="aui_layer">0</property>
+                    <property name="aui_name"></property>
+                    <property name="aui_position">0</property>
+                    <property name="aui_row">0</property>
+                    <property name="auth_needed">0</property>
+                    <property name="best_size"></property>
+                    <property name="bg"></property>
+                    <property name="bitmap"></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="current"></property>
+                    <property name="default">0</property>
+                    <property name="default_pane">0</property>
+                    <property name="disabled"></property>
+                    <property name="dock">Dock</property>
+                    <property name="dock_fixed">0</property>
+                    <property name="docking">Left</property>
+                    <property name="drag_accept_files">0</property>
+                    <property name="enabled">1</property>
+                    <property name="fg"></property>
+                    <property name="floatable">1</property>
+                    <property name="focus"></property>
+                    <property name="font"></property>
+                    <property name="gripper">0</property>
+                    <property name="hidden">0</property>
+                    <property name="id">wxID_ANY</property>
+                    <property name="label">MyButton</property>
+                    <property name="margins"></property>
+                    <property name="markup">0</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_buttonOutputAdd</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="position"></property>
+                    <property name="pressed"></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"></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="OnButtonClick">OnAddOutputClick</event>
+                  </object>
+                </object>
+              </object>
+            </object>
+            <object class="sizeritem" expanded="true">
+              <property name="border">0</property>
+              <property name="flag">wxEXPAND | wxALL</property>
+              <property name="proportion">1</property>
+              <object class="wxScrolledWindow" expanded="true">
+                <property name="BottomDockable">1</property>
+                <property name="LeftDockable">1</property>
+                <property name="RightDockable">1</property>
+                <property name="TopDockable">1</property>
+                <property name="aui_layer">0</property>
+                <property name="aui_name"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</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="drag_accept_files">0</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"></property>
+                <property name="moveable">1</property>
+                <property name="name">m_outputList</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="scroll_rate_x">5</property>
+                <property name="scroll_rate_y">5</property>
+                <property name="show">1</property>
+                <property name="size"></property>
+                <property name="subclass">; ; forward_declare</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">wxVSCROLL</property>
+                <object class="wxBoxSizer" expanded="true">
+                  <property name="minimum_size"></property>
+                  <property name="name">m_outputListSizer</property>
+                  <property name="orient">wxVERTICAL</property>
+                  <property name="permission">protected</property>
+                </object>
+              </object>
+            </object>
+            <object class="sizeritem" expanded="false">
+              <property name="border">5</property>
+              <property name="flag">wxALIGN_RIGHT|wxALL</property>
+              <property name="proportion">0</property>
+              <object class="wxButton" expanded="false">
+                <property name="BottomDockable">1</property>
+                <property name="LeftDockable">1</property>
+                <property name="RightDockable">1</property>
+                <property name="TopDockable">1</property>
+                <property name="aui_layer">0</property>
+                <property name="aui_name"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</property>
+                <property name="auth_needed">0</property>
+                <property name="best_size"></property>
+                <property name="bg">wxSYS_COLOUR_WINDOW</property>
+                <property name="bitmap"></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="current"></property>
+                <property name="default">0</property>
+                <property name="default_pane">0</property>
+                <property name="disabled"></property>
+                <property name="dock">Dock</property>
+                <property name="dock_fixed">0</property>
+                <property name="docking">Left</property>
+                <property name="drag_accept_files">0</property>
+                <property name="enabled">1</property>
+                <property name="fg"></property>
+                <property name="floatable">1</property>
+                <property name="focus"></property>
+                <property name="font"></property>
+                <property name="gripper">0</property>
+                <property name="hidden">0</property>
+                <property name="id">wxID_ANY</property>
+                <property name="label">Run All Jobs</property>
+                <property name="margins"></property>
+                <property name="markup">0</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_buttonRunAllOutputs</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="position"></property>
+                <property name="pressed"></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"></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="OnButtonClick">OnRunAllJobsClick</event>
+              </object>
+            </object>
+          </object>
+        </object>
+      </object>
+    </object>
+    <object class="Panel" expanded="true">
+      <property name="aui_managed">0</property>
+      <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
+      <property name="bg">wxSYS_COLOUR_3DLIGHT</property>
+      <property name="context_help"></property>
+      <property name="context_menu">1</property>
+      <property name="drag_accept_files">0</property>
+      <property name="enabled">1</property>
+      <property name="event_handler">impl_virtual</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"></property>
+      <property name="name">PANEL_JOB_OUTPUT_BASE</property>
+      <property name="pos"></property>
+      <property name="size">-1,-1</property>
+      <property name="subclass">; ; forward_declare</property>
+      <property name="tooltip"></property>
+      <property name="two_step_creation">0</property>
+      <property name="window_extra_style"></property>
+      <property name="window_name"></property>
+      <property name="window_style">wxBORDER_SIMPLE|wxTAB_TRAVERSAL</property>
+      <object class="wxBoxSizer" expanded="true">
+        <property name="minimum_size"></property>
+        <property name="name">bSizer11</property>
+        <property name="orient">wxHORIZONTAL</property>
+        <property name="permission">none</property>
+        <object class="sizeritem" expanded="true">
+          <property name="border">5</property>
+          <property name="flag">wxALL</property>
+          <property name="proportion">0</property>
+          <object class="wxStaticBitmap" expanded="true">
+            <property name="BottomDockable">1</property>
+            <property name="LeftDockable">1</property>
+            <property name="RightDockable">1</property>
+            <property name="TopDockable">1</property>
+            <property name="aui_layer">0</property>
+            <property name="aui_name"></property>
+            <property name="aui_position">0</property>
+            <property name="aui_row">0</property>
+            <property name="best_size"></property>
+            <property name="bg"></property>
+            <property name="bitmap"></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="drag_accept_files">0</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"></property>
+            <property name="moveable">1</property>
+            <property name="name">m_bitmapOutputType</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">; ; forward_declare</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"></property>
+          </object>
+        </object>
+        <object class="sizeritem" expanded="true">
+          <property name="border">5</property>
+          <property name="flag">wxEXPAND</property>
+          <property name="proportion">1</property>
+          <object class="wxBoxSizer" expanded="true">
+            <property name="minimum_size"></property>
+            <property name="name">bSizer12</property>
+            <property name="orient">wxVERTICAL</property>
+            <property name="permission">none</property>
+            <object class="sizeritem" expanded="true">
+              <property name="border">5</property>
+              <property name="flag">wxALL</property>
+              <property name="proportion">0</property>
+              <object class="wxStaticText" expanded="true">
+                <property name="BottomDockable">1</property>
+                <property name="LeftDockable">1</property>
+                <property name="RightDockable">1</property>
+                <property name="TopDockable">1</property>
+                <property name="aui_layer">0</property>
+                <property name="aui_name"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</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="drag_accept_files">0</property>
+                <property name="enabled">1</property>
+                <property name="fg"></property>
+                <property name="floatable">1</property>
+                <property name="font">,90,700,-1,70,0</property>
+                <property name="gripper">0</property>
+                <property name="hidden">0</property>
+                <property name="id">wxID_ANY</property>
+                <property name="label">Placeholder</property>
+                <property name="markup">0</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_textOutputType</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"></property>
+                <property name="window_extra_style"></property>
+                <property name="window_name"></property>
+                <property name="window_style"></property>
+                <property name="wrap">-1</property>
+              </object>
+            </object>
+          </object>
+        </object>
+        <object class="sizeritem" expanded="true">
+          <property name="border">5</property>
+          <property name="flag">wxEXPAND</property>
+          <property name="proportion">0</property>
+          <object class="wxBoxSizer" expanded="true">
+            <property name="minimum_size"></property>
+            <property name="name">bSizer13</property>
+            <property name="orient">wxVERTICAL</property>
+            <property name="permission">none</property>
+            <object class="sizeritem" expanded="true">
+              <property name="border">5</property>
+              <property name="flag">wxALL</property>
+              <property name="proportion">0</property>
+              <object class="wxBitmapButton" expanded="true">
+                <property name="BottomDockable">1</property>
+                <property name="LeftDockable">1</property>
+                <property name="RightDockable">1</property>
+                <property name="TopDockable">1</property>
+                <property name="aui_layer">0</property>
+                <property name="aui_name"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</property>
+                <property name="auth_needed">0</property>
+                <property name="best_size"></property>
+                <property name="bg"></property>
+                <property name="bitmap"></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="current"></property>
+                <property name="default">0</property>
+                <property name="default_pane">0</property>
+                <property name="disabled"></property>
+                <property name="dock">Dock</property>
+                <property name="dock_fixed">0</property>
+                <property name="docking">Left</property>
+                <property name="drag_accept_files">0</property>
+                <property name="enabled">1</property>
+                <property name="fg"></property>
+                <property name="floatable">1</property>
+                <property name="focus"></property>
+                <property name="font"></property>
+                <property name="gripper">0</property>
+                <property name="hidden">0</property>
+                <property name="id">wxID_ANY</property>
+                <property name="label">Run</property>
+                <property name="margins"></property>
+                <property name="markup">0</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_buttonOutputRun</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="position"></property>
+                <property name="pressed"></property>
+                <property name="resize">Resizable</property>
+                <property name="show">1</property>
+                <property name="size"></property>
+                <property name="style"></property>
+                <property name="subclass"></property>
+                <property name="toolbar_pane">0</property>
+                <property name="tooltip"></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="OnButtonClick">OnOutputRunClick</event>
+              </object>
+            </object>
+            <object class="sizeritem" expanded="true">
+              <property name="border">5</property>
+              <property name="flag">wxALL</property>
+              <property name="proportion">0</property>
+              <object class="wxBitmapButton" expanded="true">
+                <property name="BottomDockable">1</property>
+                <property name="LeftDockable">1</property>
+                <property name="RightDockable">1</property>
+                <property name="TopDockable">1</property>
+                <property name="aui_layer">0</property>
+                <property name="aui_name"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</property>
+                <property name="auth_needed">0</property>
+                <property name="best_size"></property>
+                <property name="bg"></property>
+                <property name="bitmap"></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="current"></property>
+                <property name="default">0</property>
+                <property name="default_pane">0</property>
+                <property name="disabled"></property>
+                <property name="dock">Dock</property>
+                <property name="dock_fixed">0</property>
+                <property name="docking">Left</property>
+                <property name="drag_accept_files">0</property>
+                <property name="enabled">1</property>
+                <property name="fg"></property>
+                <property name="floatable">1</property>
+                <property name="focus"></property>
+                <property name="font"></property>
+                <property name="gripper">0</property>
+                <property name="hidden">0</property>
+                <property name="id">wxID_ANY</property>
+                <property name="label">Options</property>
+                <property name="margins"></property>
+                <property name="markup">0</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_buttonOutputOptions</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="position"></property>
+                <property name="pressed"></property>
+                <property name="resize">Resizable</property>
+                <property name="show">1</property>
+                <property name="size"></property>
+                <property name="style"></property>
+                <property name="subclass"></property>
+                <property name="toolbar_pane">0</property>
+                <property name="tooltip"></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="OnButtonClick">OnOutputOptionsClick</event>
+              </object>
+            </object>
+          </object>
+        </object>
+      </object>
+    </object>
+    <object class="Dialog" expanded="true">
+      <property name="aui_managed">0</property>
+      <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
+      <property name="bg"></property>
+      <property name="center">wxBOTH</property>
+      <property name="context_help"></property>
+      <property name="context_menu">1</property>
+      <property name="drag_accept_files">0</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"></property>
+      <property name="name">DIALOG_JOB_OUTPUT_BASE</property>
+      <property name="pos"></property>
+      <property name="size">495,369</property>
+      <property name="style">wxDEFAULT_DIALOG_STYLE</property>
+      <property name="subclass">DIALOG_SHIM; dialog_shim.h; forward_declare</property>
+      <property name="title"></property>
+      <property name="tooltip"></property>
+      <property name="two_step_creation">0</property>
+      <property name="window_extra_style"></property>
+      <property name="window_name"></property>
+      <property name="window_style"></property>
+      <object class="wxBoxSizer" expanded="true">
+        <property name="minimum_size"></property>
+        <property name="name">bSizer15</property>
+        <property name="orient">wxVERTICAL</property>
+        <property name="permission">none</property>
+        <object class="sizeritem" expanded="true">
+          <property name="border">5</property>
+          <property name="flag">wxALL</property>
+          <property name="proportion">0</property>
+          <object class="wxStaticText" expanded="true">
+            <property name="BottomDockable">1</property>
+            <property name="LeftDockable">1</property>
+            <property name="RightDockable">1</property>
+            <property name="TopDockable">1</property>
+            <property name="aui_layer">0</property>
+            <property name="aui_name"></property>
+            <property name="aui_position">0</property>
+            <property name="aui_row">0</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="drag_accept_files">0</property>
+            <property name="enabled">1</property>
+            <property name="fg"></property>
+            <property name="floatable">1</property>
+            <property name="font">,90,700,-1,70,0</property>
+            <property name="gripper">0</property>
+            <property name="hidden">0</property>
+            <property name="id">wxID_ANY</property>
+            <property name="label">Options</property>
+            <property name="markup">0</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_staticText9</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"></property>
+            <property name="window_extra_style"></property>
+            <property name="window_name"></property>
+            <property name="window_style"></property>
+            <property name="wrap">-1</property>
+          </object>
+        </object>
+        <object class="sizeritem" expanded="true">
+          <property name="border">5</property>
+          <property name="flag">wxEXPAND | wxALL</property>
+          <property name="proportion">1</property>
+          <object class="wxPanel" expanded="true">
+            <property name="BottomDockable">1</property>
+            <property name="LeftDockable">1</property>
+            <property name="RightDockable">1</property>
+            <property name="TopDockable">1</property>
+            <property name="aui_layer">0</property>
+            <property name="aui_name"></property>
+            <property name="aui_position">0</property>
+            <property name="aui_row">0</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="drag_accept_files">0</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"></property>
+            <property name="moveable">1</property>
+            <property name="name">m_panel9</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">; ; forward_declare</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 class="wxFlexGridSizer" expanded="true">
+              <property name="cols">2</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">fgSizer1</property>
+              <property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
+              <property name="permission">none</property>
+              <property name="rows">0</property>
+              <property name="vgap">0</property>
+              <object class="sizeritem" expanded="true">
+                <property name="border">5</property>
+                <property name="flag">wxALL</property>
+                <property name="proportion">0</property>
+                <object class="wxStaticText" expanded="true">
+                  <property name="BottomDockable">1</property>
+                  <property name="LeftDockable">1</property>
+                  <property name="RightDockable">1</property>
+                  <property name="TopDockable">1</property>
+                  <property name="aui_layer">0</property>
+                  <property name="aui_name"></property>
+                  <property name="aui_position">0</property>
+                  <property name="aui_row">0</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="drag_accept_files">0</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">Format</property>
+                  <property name="markup">0</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_textArchiveFormat</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"></property>
+                  <property name="window_extra_style"></property>
+                  <property name="window_name"></property>
+                  <property name="window_style"></property>
+                  <property name="wrap">-1</property>
+                </object>
+              </object>
+              <object class="sizeritem" expanded="true">
+                <property name="border">5</property>
+                <property name="flag">wxALL</property>
+                <property name="proportion">0</property>
+                <object class="wxChoice" expanded="true">
+                  <property name="BottomDockable">1</property>
+                  <property name="LeftDockable">1</property>
+                  <property name="RightDockable">1</property>
+                  <property name="TopDockable">1</property>
+                  <property name="aui_layer">0</property>
+                  <property name="aui_name"></property>
+                  <property name="aui_position">0</property>
+                  <property name="aui_row">0</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="choices"></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="drag_accept_files">0</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"></property>
+                  <property name="moveable">1</property>
+                  <property name="name">m_choiceArchiveformat</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="selection">0</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"></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>
+                </object>
+              </object>
+              <object class="sizeritem" expanded="true">
+                <property name="border">5</property>
+                <property name="flag">wxALL</property>
+                <property name="proportion">0</property>
+                <object class="wxStaticText" expanded="true">
+                  <property name="BottomDockable">1</property>
+                  <property name="LeftDockable">1</property>
+                  <property name="RightDockable">1</property>
+                  <property name="TopDockable">1</property>
+                  <property name="aui_layer">0</property>
+                  <property name="aui_name"></property>
+                  <property name="aui_position">0</property>
+                  <property name="aui_row">0</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="drag_accept_files">0</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">Output Path</property>
+                  <property name="markup">0</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_textOutputPath</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"></property>
+                  <property name="window_extra_style"></property>
+                  <property name="window_name"></property>
+                  <property name="window_style"></property>
+                  <property name="wrap">-1</property>
+                </object>
+              </object>
+              <object class="sizeritem" expanded="true">
+                <property name="border">5</property>
+                <property name="flag">wxEXPAND</property>
+                <property name="proportion">1</property>
+                <object class="wxBoxSizer" expanded="true">
+                  <property name="minimum_size"></property>
+                  <property name="name">bSizer16</property>
+                  <property name="orient">wxHORIZONTAL</property>
+                  <property name="permission">none</property>
+                  <object class="sizeritem" expanded="true">
+                    <property name="border">5</property>
+                    <property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
+                    <property name="proportion">0</property>
+                    <object class="wxTextCtrl" expanded="true">
+                      <property name="BottomDockable">1</property>
+                      <property name="LeftDockable">1</property>
+                      <property name="RightDockable">1</property>
+                      <property name="TopDockable">1</property>
+                      <property name="aui_layer">0</property>
+                      <property name="aui_name"></property>
+                      <property name="aui_position">0</property>
+                      <property name="aui_row">0</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="drag_accept_files">0</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="maxlength">0</property>
+                      <property name="min_size"></property>
+                      <property name="minimize_button">0</property>
+                      <property name="minimum_size">350,-1</property>
+                      <property name="moveable">1</property>
+                      <property name="name">m_textCtrlOutputPath</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"></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="value"></property>
+                      <property name="window_extra_style"></property>
+                      <property name="window_name"></property>
+                      <property name="window_style"></property>
+                    </object>
+                  </object>
+                  <object class="sizeritem" expanded="true">
+                    <property name="border">5</property>
+                    <property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
+                    <property name="proportion">0</property>
+                    <object class="wxBitmapButton" expanded="true">
+                      <property name="BottomDockable">1</property>
+                      <property name="LeftDockable">1</property>
+                      <property name="RightDockable">1</property>
+                      <property name="TopDockable">1</property>
+                      <property name="aui_layer">0</property>
+                      <property name="aui_name"></property>
+                      <property name="aui_position">0</property>
+                      <property name="aui_row">0</property>
+                      <property name="auth_needed">0</property>
+                      <property name="best_size"></property>
+                      <property name="bg"></property>
+                      <property name="bitmap"></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="current"></property>
+                      <property name="default">0</property>
+                      <property name="default_pane">0</property>
+                      <property name="disabled"></property>
+                      <property name="dock">Dock</property>
+                      <property name="dock_fixed">0</property>
+                      <property name="docking">Left</property>
+                      <property name="drag_accept_files">0</property>
+                      <property name="enabled">1</property>
+                      <property name="fg"></property>
+                      <property name="floatable">1</property>
+                      <property name="focus"></property>
+                      <property name="font"></property>
+                      <property name="gripper">0</property>
+                      <property name="hidden">0</property>
+                      <property name="id">wxID_ANY</property>
+                      <property name="label">MyButton</property>
+                      <property name="margins"></property>
+                      <property name="markup">0</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_buttonOutputPath</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="position"></property>
+                      <property name="pressed"></property>
+                      <property name="resize">Resizable</property>
+                      <property name="show">1</property>
+                      <property name="size"></property>
+                      <property name="style"></property>
+                      <property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
+                      <property name="toolbar_pane">0</property>
+                      <property name="tooltip"></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="OnButtonClick">onOutputPathBrowseClicked</event>
+                    </object>
+                  </object>
+                </object>
+              </object>
+              <object class="sizeritem" expanded="true">
+                <property name="border">5</property>
+                <property name="flag">wxALL</property>
+                <property name="proportion">0</property>
+                <object class="wxStaticText" expanded="true">
+                  <property name="BottomDockable">1</property>
+                  <property name="LeftDockable">1</property>
+                  <property name="RightDockable">1</property>
+                  <property name="TopDockable">1</property>
+                  <property name="aui_layer">0</property>
+                  <property name="aui_name"></property>
+                  <property name="aui_position">0</property>
+                  <property name="aui_row">0</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="drag_accept_files">0</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">Only Jobs</property>
+                  <property name="markup">0</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_staticText10</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"></property>
+                  <property name="window_extra_style"></property>
+                  <property name="window_name"></property>
+                  <property name="window_style"></property>
+                  <property name="wrap">-1</property>
+                </object>
+              </object>
+              <object class="sizeritem" expanded="true">
+                <property name="border">5</property>
+                <property name="flag">wxALL</property>
+                <property name="proportion">0</property>
+                <object class="wxListBox" expanded="true">
+                  <property name="BottomDockable">1</property>
+                  <property name="LeftDockable">1</property>
+                  <property name="RightDockable">1</property>
+                  <property name="TopDockable">1</property>
+                  <property name="aui_layer">0</property>
+                  <property name="aui_name"></property>
+                  <property name="aui_position">0</property>
+                  <property name="aui_row">0</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="choices"></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="drag_accept_files">0</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">300,200</property>
+                  <property name="moveable">1</property>
+                  <property name="name">m_listBoxOnly</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">wxLB_ALWAYS_SB|wxLB_MULTIPLE</property>
+                  <property name="subclass">; ; forward_declare</property>
+                  <property name="toolbar_pane">0</property>
+                  <property name="tooltip"></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>
+                </object>
+              </object>
+            </object>
+          </object>
+        </object>
+        <object class="sizeritem" expanded="true">
+          <property name="border">5</property>
+          <property name="flag">wxEXPAND</property>
+          <property name="proportion">0</property>
+          <object class="wxStdDialogButtonSizer" expanded="true">
+            <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">0</property>
+            <property name="Save">1</property>
+            <property name="Yes">0</property>
+            <property name="minimum_size"></property>
+            <property name="name">m_sdbSizer1</property>
+            <property name="permission">protected</property>
+          </object>
+        </object>
+      </object>
+    </object>
+  </object>
+</wxFormBuilder_Project>
diff --git a/kicad/dialogs/panel_jobs_base.h b/kicad/dialogs/panel_jobs_base.h
new file mode 100644
index 0000000000..5b7b73b1ea
--- /dev/null
+++ b/kicad/dialogs/panel_jobs_base.h
@@ -0,0 +1,134 @@
+///////////////////////////////////////////////////////////////////////////
+// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
+// http://www.wxformbuilder.org/
+//
+// PLEASE DO *NOT* EDIT THIS FILE!
+///////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include <wx/artprov.h>
+#include <wx/xrc/xmlres.h>
+class STD_BITMAP_BUTTON;
+
+#include "dialogs/panel_notebook_base.h"
+#include "dialog_shim.h"
+#include <wx/string.h>
+#include <wx/stattext.h>
+#include <wx/gdicmn.h>
+#include <wx/font.h>
+#include <wx/colour.h>
+#include <wx/settings.h>
+#include <wx/listctrl.h>
+#include <wx/bmpbuttn.h>
+#include <wx/bitmap.h>
+#include <wx/image.h>
+#include <wx/icon.h>
+#include <wx/button.h>
+#include <wx/sizer.h>
+#include <wx/scrolwin.h>
+#include <wx/panel.h>
+#include <wx/statbmp.h>
+#include <wx/choice.h>
+#include <wx/textctrl.h>
+#include <wx/listbox.h>
+#include <wx/dialog.h>
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+/// Class PANEL_JOBS_BASE
+///////////////////////////////////////////////////////////////////////////////
+class PANEL_JOBS_BASE : public PANEL_NOTEBOOK_BASE
+{
+	private:
+
+	protected:
+		wxStaticText* m_staticText1;
+		wxListCtrl* m_jobList;
+		wxBitmapButton* m_buttonAddJob;
+		wxBitmapButton* m_buttonUp;
+		wxBitmapButton* m_buttonDown;
+		wxButton* m_buttonSave;
+		wxStaticText* m_staticText4;
+		wxBitmapButton* m_buttonOutputAdd;
+		wxScrolledWindow* m_outputList;
+		wxBoxSizer* m_outputListSizer;
+		wxButton* m_buttonRunAllOutputs;
+
+		// Virtual event handlers, override them in your derived class
+		virtual void OnJobListDoubleClicked( wxListEvent& event ) { event.Skip(); }
+		virtual void OnJobListItemRightClick( wxListEvent& event ) { event.Skip(); }
+		virtual void OnAddJobClick( wxCommandEvent& event ) { event.Skip(); }
+		virtual void OnSaveButtonClick( wxCommandEvent& event ) { event.Skip(); }
+		virtual void OnAddOutputClick( wxCommandEvent& event ) { event.Skip(); }
+		virtual void OnRunAllJobsClick( wxCommandEvent& event ) { event.Skip(); }
+
+
+	public:
+
+		PANEL_JOBS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 600,400 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
+
+		~PANEL_JOBS_BASE();
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+/// Class PANEL_JOB_OUTPUT_BASE
+///////////////////////////////////////////////////////////////////////////////
+class PANEL_JOB_OUTPUT_BASE : public wxPanel
+{
+	private:
+
+	protected:
+		wxStaticBitmap* m_bitmapOutputType;
+		wxStaticText* m_textOutputType;
+		wxBitmapButton* m_buttonOutputRun;
+		wxBitmapButton* m_buttonOutputOptions;
+
+		// Virtual event handlers, override them in your derived class
+		virtual void OnOutputRunClick( wxCommandEvent& event ) { event.Skip(); }
+		virtual void OnOutputOptionsClick( wxCommandEvent& event ) { event.Skip(); }
+
+
+	public:
+
+		PANEL_JOB_OUTPUT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxBORDER_SIMPLE|wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
+
+		~PANEL_JOB_OUTPUT_BASE();
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+/// Class DIALOG_JOB_OUTPUT_BASE
+///////////////////////////////////////////////////////////////////////////////
+class DIALOG_JOB_OUTPUT_BASE : public DIALOG_SHIM
+{
+	private:
+
+	protected:
+		wxStaticText* m_staticText9;
+		wxPanel* m_panel9;
+		wxStaticText* m_textArchiveFormat;
+		wxChoice* m_choiceArchiveformat;
+		wxStaticText* m_textOutputPath;
+		wxTextCtrl* m_textCtrlOutputPath;
+		STD_BITMAP_BUTTON* m_buttonOutputPath;
+		wxStaticText* m_staticText10;
+		wxListBox* m_listBoxOnly;
+		wxStdDialogButtonSizer* m_sdbSizer1;
+		wxButton* m_sdbSizer1Save;
+		wxButton* m_sdbSizer1Cancel;
+
+		// Virtual event handlers, override them in your derived class
+		virtual void onOutputPathBrowseClicked( wxCommandEvent& event ) { event.Skip(); }
+
+
+	public:
+
+		DIALOG_JOB_OUTPUT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 495,369 ), long style = wxDEFAULT_DIALOG_STYLE );
+
+		~DIALOG_JOB_OUTPUT_BASE();
+
+};
+
diff --git a/kicad/jobs_runner.cpp b/kicad/jobs_runner.cpp
new file mode 100644
index 0000000000..b5a1b5aa4a
--- /dev/null
+++ b/kicad/jobs_runner.cpp
@@ -0,0 +1,169 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <jobs_runner.h>
+#include <jobs/job_registry.h>
+#include <jobs/jobset.h>
+#include <kiway.h>
+#include <kiway_express.h>
+#include <reporter.h>
+
+JOBS_RUNNER::JOBS_RUNNER( KIWAY* aKiway, JOBSET* aJobsFile,
+                          REPORTER* aReporter ) :
+        m_kiway( aKiway ),
+        m_jobsFile( aJobsFile ),
+        m_reporter( aReporter )
+{
+    if( !m_reporter )
+    {
+        m_reporter = &NULL_REPORTER::GetInstance();
+    }
+}
+
+
+bool JOBS_RUNNER::RunJobsAllOutputs( bool aBail )
+{
+    bool success = true;
+
+    for( JOBSET_OUTPUT& output : m_jobsFile->GetOutputs() )
+    {
+        success &= RunJobsForOutput( &output, aBail );
+    }
+
+    return success;
+}
+
+
+bool JOBS_RUNNER::RunJobsForOutput( JOBSET_OUTPUT* aOutput, bool aBail )
+{
+    bool                       success = true;
+    std::vector<JOBSET_JOB> jobsForOutput = m_jobsFile->GetJobsForOutput( aOutput );
+    wxString msg;
+
+    wxFileName tmp;
+    tmp.AssignDir( wxFileName::GetTempDir() );
+    tmp.AppendDir( KIID().AsString() );
+
+    wxString tempDirPath = tmp.GetFullPath();
+    if( !wxFileName::Mkdir( tempDirPath, wxS_DIR_DEFAULT ) )
+    {
+		if( m_reporter )
+		{
+			msg = wxString::Format( wxT( "Failed to create temporary directory %s" ), tempDirPath );
+			m_reporter->Report( msg, RPT_SEVERITY_ERROR );
+		}
+
+		return false;
+    }
+
+    if( m_reporter != nullptr )
+    {
+        msg += wxT( "|--------------------------------\n" );
+        msg += wxT( "| " );
+        msg += wxString::Format( "Performing jobs" );
+        msg += wxT( "\n" );
+        msg += wxT( "|--------------------------------\n" );
+
+        msg += wxString::Format( wxT( "|%-5s | %-50s\n" ), wxT( "No." ), wxT( "Description" ) );
+
+        int jobNum = 1;
+        for( const JOBSET_JOB& job : jobsForOutput )
+        {
+            msg += wxString::Format( wxT( "|%-5d | %-50s\n" ), jobNum,
+                                               job.m_job->GetDescription() );
+            jobNum++;
+        }
+        msg += wxT( "|--------------------------------\n" );
+        msg += wxT( "\n" );
+        msg += wxT( "\n" );
+
+        m_reporter->Report( msg, RPT_SEVERITY_INFO );
+    }
+
+    std::vector<JOB_OUTPUT> outputs;
+
+    int jobNum = 1;
+    int failCount = 0;
+    int successCount = 0;
+    for( const JOBSET_JOB& job : jobsForOutput )
+    {
+        if( m_reporter != nullptr )
+        {
+            msg = wxT( "|--------------------------------\n" );
+            msg += wxString::Format( wxT( "| Running job %d, %s" ), jobNum, job.m_job->GetDescription() );
+            msg += _( "\n" );
+            msg += wxT( "|--------------------------------\n" );
+
+            m_reporter->Report( msg, RPT_SEVERITY_INFO );
+        }
+
+        KIWAY::FACE_T iface = JOB_REGISTRY::GetKifaceType( job.m_type );
+
+        job.m_job->SetTempOutputDirectory( tempDirPath );
+
+        int result = m_kiway->ProcessJob( iface, job.m_job );
+
+        if( m_reporter )
+        {
+            if( result == 0 )
+            {
+                msg = _( "\033[32;1mJob successful\033[0m\n" );
+
+                successCount++;
+            }
+            else
+            {
+                msg = _(  "\033[31;1mJob failed\033[0m\n" );
+
+                failCount++;
+            }
+
+            msg += _( "\n\n" );
+            m_reporter->Report( msg, RPT_SEVERITY_INFO );
+        }
+
+        if( result != 0 )
+        {
+            if( aBail )
+            {
+                return result;
+            }
+            else
+            {
+                success = false;
+            }
+        }
+    }
+
+    if( success )
+    {
+        aOutput->m_outputHandler->HandleOutputs( tempDirPath, outputs );
+    }
+
+    if( m_reporter )
+    {
+        msg = wxString::Format( _( "\n\n\033[33;1m%d jobs succeeded, %d job failed\033[0m\n" ),
+                                successCount, failCount );
+
+        m_reporter->Report( msg, RPT_SEVERITY_INFO );
+    }
+
+	return success;
+}
\ No newline at end of file
diff --git a/kicad/jobs_runner.h b/kicad/jobs_runner.h
new file mode 100644
index 0000000000..9dcc74c49b
--- /dev/null
+++ b/kicad/jobs_runner.h
@@ -0,0 +1,40 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
+ * Copyright (C) 2024 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+class JOBSET;
+struct JOBSET_OUTPUT;
+class KIWAY;
+class REPORTER;
+
+class JOBS_RUNNER
+{
+public:
+    JOBS_RUNNER( KIWAY* aKiway, JOBSET* aJobsFile, REPORTER* aReporter = nullptr );
+
+    bool RunJobsAllOutputs( bool aBail = false );
+    bool RunJobsForOutput( JOBSET_OUTPUT* aOutput, bool aBail = false );
+
+private:
+    KIWAY*     m_kiway;
+    JOBSET*         m_jobsFile;
+    REPORTER*          m_reporter;
+};
\ No newline at end of file
diff --git a/kicad/kicad_cli.cpp b/kicad/kicad_cli.cpp
index ffa65723a6..32af3a4c68 100644
--- a/kicad/kicad_cli.cpp
+++ b/kicad/kicad_cli.cpp
@@ -46,6 +46,8 @@
 #include <kiplatform/environment.h>
 #include <locale_io.h>
 
+#include "cli/command_jobset.h"
+#include "cli/command_jobset_run.h"
 #include "cli/command_pcb.h"
 #include "cli/command_pcb_export.h"
 #include "cli/command_pcb_drc.h"
@@ -106,6 +108,8 @@ struct COMMAND_ENTRY
             handler( aHandler ), subCommands( aSub ){};
 };
 
+static CLI::JOBSET_COMMAND               jobsetCmd{};
+static CLI::JOBSET_RUN_COMMAND           jobsetRunCmd{};
 static CLI::PCB_COMMAND                  pcbCmd{};
 static CLI::PCB_DRC_COMMAND              pcbDrcCmd{};
 static CLI::PCB_RENDER_COMMAND           pcbRenderCmd{};
@@ -147,6 +151,14 @@ static CLI::VERSION_COMMAND              versionCmd{};
 
 
 static std::vector<COMMAND_ENTRY> commandStack = {
+    {
+        &jobsetCmd,
+        {
+            {
+                &jobsetRunCmd
+            }
+        }
+    },
     {
         &fpCmd,
         {
diff --git a/kicad/kicad_id.h b/kicad/kicad_id.h
index 60e6cd8228..9630f60c39 100644
--- a/kicad/kicad_id.h
+++ b/kicad/kicad_id.h
@@ -94,6 +94,8 @@ enum id_kicad_frm {
     ID_GIT_SWITCH_QUICK4,       // Switch the local repository to the fourth quick branch
     ID_GIT_SWITCH_QUICK5,       // Switch the local repository to the fifth quick branch
 
+    ID_JOBS_RUN,
+
     // Please, verify: the number of items in this list should be
     // less than ROOM_FOR_KICADMANAGER (see id.h)
     ID_KICADMANAGER_END_LIST
diff --git a/kicad/kicad_manager_frame.cpp b/kicad/kicad_manager_frame.cpp
index 3a1b692037..cc0be494ae 100644
--- a/kicad/kicad_manager_frame.cpp
+++ b/kicad/kicad_manager_frame.cpp
@@ -35,6 +35,7 @@
 #include <build_version.h>
 #include <dialogs/panel_kicad_launcher.h>
 #include <dialogs/dialog_update_check_prompt.h>
+#include <dialogs/panel_jobs.h>
 #include <eda_base_frame.h>
 #include <executable_names.h>
 #include <file_history.h>
@@ -67,7 +68,7 @@
 #include <wx/process.h>
 #include <atomic>
 #include <update_manager.h>
-
+#include <jobs/jobset.h>
 
 #include <../pcbnew/pcb_io/kicad_sexpr/pcb_io_kicad_sexpr.h>   // for SEXPR_BOARD_FILE_VERSION def
 
@@ -117,6 +118,8 @@ BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME )
 END_EVENT_TABLE()
 
 
+    static JOBSET* test = new JOBSET( "" );
+
 // See below the purpose of this include
 #include <wx/xml/xml.h>
 
@@ -704,6 +707,33 @@ bool KICAD_MANAGER_FRAME::CloseProject( bool aSave )
 }
 
 
+void KICAD_MANAGER_FRAME::OpenJobsFile( const wxFileName& aFileName, bool aCreate )
+{
+    if( !ADVANCED_CFG::GetCfg().m_EnableJobset )
+    {
+        return;
+    }
+
+    try
+    {
+        std::unique_ptr<JOBSET> jobsFile =
+                std::make_unique<JOBSET>( aFileName.GetFullPath().ToStdString() );
+
+        jobsFile->LoadFromFile();
+
+        PANEL_JOBS* jobPanel = new PANEL_JOBS( m_notebook, this, std::move( jobsFile ) );
+        jobPanel->SetProjectTied( true );
+        jobPanel->SetClosable( true );
+        m_notebook->AddPage( jobPanel, aFileName.GetFullName(),
+                             true );
+    }
+    catch( ... )
+    {
+
+    }
+}
+
+
 void KICAD_MANAGER_FRAME::LoadProject( const wxFileName& aProjectFileName )
 {
     // The project file should be valid by the time we get here or something has gone wrong.
diff --git a/kicad/kicad_manager_frame.h b/kicad/kicad_manager_frame.h
index e00b7640fa..7d321ea34e 100644
--- a/kicad/kicad_manager_frame.h
+++ b/kicad/kicad_manager_frame.h
@@ -142,6 +142,8 @@ public:
     bool CloseProject( bool aSave );
     void LoadProject( const wxFileName& aProjectFileName );
 
+    void OpenJobsFile( const wxFileName& aFileName, bool aCreate = false );
+
 
     void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
 
diff --git a/kicad/menubar.cpp b/kicad/menubar.cpp
index e12b6778d8..6432bb2651 100644
--- a/kicad/menubar.cpp
+++ b/kicad/menubar.cpp
@@ -81,6 +81,11 @@ void KICAD_MANAGER_FRAME::doReCreateMenuBar()
         fileMenu->Add( KICAD_MANAGER_ACTIONS::newFromRepository );
     }
 
+    if( ADVANCED_CFG::GetCfg().m_EnableJobset )
+    {
+        fileMenu->Add( KICAD_MANAGER_ACTIONS::newJobsetFile );
+    }
+
     if( wxDir::Exists( PATHS::GetStockDemosPath() ) )
     {
         fileMenu->Add( KICAD_MANAGER_ACTIONS::openDemoProject );
diff --git a/kicad/project_tree.cpp b/kicad/project_tree.cpp
index 1f9aa3bc61..ba8e71c59a 100644
--- a/kicad/project_tree.cpp
+++ b/kicad/project_tree.cpp
@@ -102,6 +102,7 @@ void PROJECT_TREE::LoadIcons()
     images.push_back( KiBitmapBundle( BITMAPS::library ) );                // TREE_SEXPR_SYMBOL_LIB_FILE
     images.push_back( KiBitmapBundle( BITMAPS::editor ) );                 // DESIGN_RULES
     images.push_back( KiBitmapBundle( BITMAPS::zip ) );                    // ZIP_ARCHIVE
+    images.push_back( KiBitmapBundle( BITMAPS::editor ) );                 // JOBSET_FILE
     SetImages( images );
 
     wxVector<wxBitmapBundle> stateImages;
@@ -176,6 +177,7 @@ void PROJECT_TREE::LoadIcons()
     m_imageList->Add( toBitmap( BITMAPS::library ) );                // TREE_SEXPR_SYMBOL_LIB_FILE
     m_imageList->Add( toBitmap( BITMAPS::editor ) );                 // DESIGN_RULES
     m_imageList->Add( toBitmap( BITMAPS::zip ) );                    // ZIP_ARCHIVE
+    m_imageList->Add( toBitmap( BITMAPS::editor ) );                 // JOBSET_FILE
 
     SetImageList( m_imageList );
 
diff --git a/kicad/project_tree_item.cpp b/kicad/project_tree_item.cpp
index 2811c0e511..6824189196 100644
--- a/kicad/project_tree_item.cpp
+++ b/kicad/project_tree_item.cpp
@@ -193,6 +193,11 @@ void PROJECT_TREE_ITEM::Activate( PROJECT_TREE_PANE* aTreePrjFrame )
 
         break;
 
+    case TREE_FILE_TYPE::JOBSET_FILE:
+        frame->OpenJobsFile( fullFileName );
+
+        break;
+
     case TREE_FILE_TYPE::DIRECTORY:
         m_parent->Toggle( id );
         break;
diff --git a/kicad/project_tree_pane.cpp b/kicad/project_tree_pane.cpp
index 6723c5c837..5701f79eda 100644
--- a/kicad/project_tree_pane.cpp
+++ b/kicad/project_tree_pane.cpp
@@ -131,6 +131,7 @@ static const wxChar* s_allowedExtensionsToList[] = {
     wxT( "^.*\\.svg$" ),           // SVG print/plot files
     wxT( "^.*\\.ps$" ),            // PostScript plot files
     wxT( "^.*\\.zip$" ),           // Zip archive files
+    wxT( "^.*\\.kicad_jobset" ),     // KiCad jobs file
     nullptr                        // end of list
 };
 
@@ -168,6 +169,7 @@ BEGIN_EVENT_TABLE( PROJECT_TREE_PANE, wxSashLayoutWindow )
     EVT_MENU( ID_GIT_ADD_TO_INDEX, PROJECT_TREE_PANE::onGitAddToIndex )
     EVT_MENU( ID_GIT_REMOVE_FROM_INDEX, PROJECT_TREE_PANE::onGitRemoveFromIndex )
 
+    EVT_MENU( ID_JOBS_RUN, PROJECT_TREE_PANE::onRunSelectedJobsFile )
 
     EVT_IDLE( PROJECT_TREE_PANE::onIdle )
     EVT_PAINT( PROJECT_TREE_PANE::onPaint )
@@ -331,6 +333,7 @@ wxString PROJECT_TREE_PANE::GetFileExt( TREE_FILE_TYPE type )
     case TREE_FILE_TYPE::SEXPR_SYMBOL_LIB_FILE: return FILEEXT::KiCadSymbolLibFileExtension;
     case TREE_FILE_TYPE::DESIGN_RULES:          return FILEEXT::DesignRulesFileExtension;
     case TREE_FILE_TYPE::ZIP_ARCHIVE:           return FILEEXT::ArchiveFileExtension;
+    case TREE_FILE_TYPE::JOBSET_FILE:          return FILEEXT::KiCadJobSetFileExtension;
 
     case TREE_FILE_TYPE::ROOT:
     case TREE_FILE_TYPE::UNKNOWN:
@@ -751,6 +754,7 @@ void PROJECT_TREE_PANE::onRight( wxTreeEvent& Event )
     bool can_edit = true;
     bool can_rename = true;
     bool can_delete = true;
+    bool run_jobs = false;
 
     bool vcs_has_repo    = m_TreeProject->GetGitRepo() != nullptr;
     bool vcs_can_commit  = hasChangedFiles();
@@ -820,6 +824,11 @@ void PROJECT_TREE_PANE::onRight( wxTreeEvent& Event )
             can_edit = false;
             break;
 
+        case TREE_FILE_TYPE::JOBSET_FILE:
+            run_jobs = true;
+            can_edit = false;
+            KI_FALLTHROUGH;
+
         case TREE_FILE_TYPE::SEXPR_SCHEMATIC:
         case TREE_FILE_TYPE::SEXPR_PCB:
             KI_FALLTHROUGH;
@@ -889,6 +898,12 @@ void PROJECT_TREE_PANE::onRight( wxTreeEvent& Event )
                            KiBitmap( BITMAPS::editor ) );
     }
 
+    if( run_jobs && selection.size() == 1 )
+    {
+        KIUI::AddMenuItem( &popup_menu, ID_JOBS_RUN, _( "Run Jobs" ), help_text,
+                           KiBitmap( BITMAPS::exchange ) );
+    }
+
     if( can_rename )
     {
         if( selection.size() == 1 )
@@ -2403,4 +2418,7 @@ void PROJECT_TREE_PANE::onGitRemoveFromIndex( wxCommandEvent& aEvent )
 }
 
 
+void PROJECT_TREE_PANE::onRunSelectedJobsFile(wxCommandEvent& event)
+{
 
+}
\ No newline at end of file
diff --git a/kicad/project_tree_pane.h b/kicad/project_tree_pane.h
index 99eb02abcf..550bc76f47 100644
--- a/kicad/project_tree_pane.h
+++ b/kicad/project_tree_pane.h
@@ -220,6 +220,11 @@ private:
     */
     void onGitRevertLocal( wxCommandEvent& event );
 
+    /**
+     * Run a selected jobs file
+     */
+    void onRunSelectedJobsFile( wxCommandEvent& event );
+
     /**
      * Updates the icons shown in the tree project to reflect the current git status
     */
diff --git a/kicad/tools/kicad_manager_actions.cpp b/kicad/tools/kicad_manager_actions.cpp
index 683fc66b33..3a6f4585ac 100644
--- a/kicad/tools/kicad_manager_actions.cpp
+++ b/kicad/tools/kicad_manager_actions.cpp
@@ -60,6 +60,13 @@ TOOL_ACTION KICAD_MANAGER_ACTIONS::newFromRepository( TOOL_ACTION_ARGS()
         .FriendlyName( _( "Clone Project from Repository..." ) )
         .Icon( BITMAPS::new_project_from_template ) );
 
+TOOL_ACTION KICAD_MANAGER_ACTIONS::newJobsetFile( TOOL_ACTION_ARGS()
+        .Name( "kicad.Control.newJobs" )
+        .Scope( AS_GLOBAL )
+        .LegacyHotkeyName( "New Jobset File" )
+        .FriendlyName( _( "New Jobset File..." ) )
+        .Icon( BITMAPS::new_document ) );
+
 TOOL_ACTION KICAD_MANAGER_ACTIONS::openDemoProject( TOOL_ACTION_ARGS()
         .Name( "kicad.Control.openDemoProject" )
         .Scope( AS_GLOBAL )
diff --git a/kicad/tools/kicad_manager_actions.h b/kicad/tools/kicad_manager_actions.h
index 040013ec8b..36cd7172e4 100644
--- a/kicad/tools/kicad_manager_actions.h
+++ b/kicad/tools/kicad_manager_actions.h
@@ -34,6 +34,7 @@ public:
     static TOOL_ACTION newProject;
     static TOOL_ACTION newFromTemplate;
     static TOOL_ACTION newFromRepository;
+    static TOOL_ACTION newJobsetFile;
     static TOOL_ACTION openDemoProject;
     static TOOL_ACTION openProject;
     static TOOL_ACTION closeProject;
diff --git a/kicad/tools/kicad_manager_control.cpp b/kicad/tools/kicad_manager_control.cpp
index 385cf5f9a8..a82070e826 100644
--- a/kicad/tools/kicad_manager_control.cpp
+++ b/kicad/tools/kicad_manager_control.cpp
@@ -205,6 +205,24 @@ int KICAD_MANAGER_CONTROL::NewFromRepository( const TOOL_EVENT& aEvent )
 }
 
 
+int KICAD_MANAGER_CONTROL::NewJobsetFile( const TOOL_EVENT& aEvent )
+{
+    wxString     default_dir = wxFileName( Prj().GetProjectFullName() ).GetPathWithSep();
+    wxFileDialog dlg( m_frame, _( "Create New Jobset" ), default_dir, wxEmptyString,
+                      FILEEXT::JobsetFileWildcard(),
+                      wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
+
+    if( dlg.ShowModal() == wxID_CANCEL )
+        return -1;
+
+    wxFileName jobsetFn( dlg.GetPath() );
+
+    m_frame->OpenJobsFile( jobsetFn.GetFullPath(), true );
+
+    return 0;
+}
+
+
 int KICAD_MANAGER_CONTROL::NewFromTemplate( const TOOL_EVENT& aEvent )
 {
     DIALOG_TEMPLATE_SELECTOR* ps = new DIALOG_TEMPLATE_SELECTOR( m_frame );
@@ -960,6 +978,7 @@ void KICAD_MANAGER_CONTROL::setTransitions()
     Go( &KICAD_MANAGER_CONTROL::NewProject,         KICAD_MANAGER_ACTIONS::newProject.MakeEvent() );
     Go( &KICAD_MANAGER_CONTROL::NewFromTemplate,    KICAD_MANAGER_ACTIONS::newFromTemplate.MakeEvent() );
     Go( &KICAD_MANAGER_CONTROL::NewFromRepository,  KICAD_MANAGER_ACTIONS::newFromRepository.MakeEvent() );
+    Go( &KICAD_MANAGER_CONTROL::NewJobsetFile,        KICAD_MANAGER_ACTIONS::newJobsetFile.MakeEvent() );
     Go( &KICAD_MANAGER_CONTROL::OpenDemoProject,    KICAD_MANAGER_ACTIONS::openDemoProject.MakeEvent() );
     Go( &KICAD_MANAGER_CONTROL::OpenProject,        KICAD_MANAGER_ACTIONS::openProject.MakeEvent() );
     Go( &KICAD_MANAGER_CONTROL::CloseProject,       KICAD_MANAGER_ACTIONS::closeProject.MakeEvent() );
diff --git a/kicad/tools/kicad_manager_control.h b/kicad/tools/kicad_manager_control.h
index bf1c2dd5b0..6e7727a580 100644
--- a/kicad/tools/kicad_manager_control.h
+++ b/kicad/tools/kicad_manager_control.h
@@ -47,6 +47,7 @@ public:
     int NewProject( const TOOL_EVENT& aEvent );
     int NewFromTemplate( const TOOL_EVENT& aEvent );
     int NewFromRepository( const TOOL_EVENT& aEvent );
+    int NewJobsetFile( const TOOL_EVENT& aEvent );
     int OpenProject( const TOOL_EVENT& aEvent );
     int OpenDemoProject( const TOOL_EVENT& aEvent );
     int CloseProject( const TOOL_EVENT& aEvent );
diff --git a/kicad/tree_file_type.h b/kicad/tree_file_type.h
index 5106e868dd..be5967da8f 100644
--- a/kicad/tree_file_type.h
+++ b/kicad/tree_file_type.h
@@ -63,6 +63,7 @@ enum class TREE_FILE_TYPE
     SEXPR_SYMBOL_LIB_FILE, // s-expression symbol library file (.kicad_sym)
     DESIGN_RULES,          // design rules (.kicad_dru)
     ZIP_ARCHIVE,           // .zip file
+    JOBSET_FILE,             // jobs (.kicad_jobs)
     MAX                    // Sentinel
 };
 
diff --git a/pcbnew/dialogs/dialog_export_2581.cpp b/pcbnew/dialogs/dialog_export_2581.cpp
index 8b27e44075..408213dab8 100644
--- a/pcbnew/dialogs/dialog_export_2581.cpp
+++ b/pcbnew/dialogs/dialog_export_2581.cpp
@@ -30,6 +30,7 @@
 #include <project/project_file.h>
 #include <settings/settings_manager.h>
 #include <widgets/std_bitmap_button.h>
+#include <jobs/job_export_pcb_ipc2581.h>
 
 #include <set>
 #include <vector>
@@ -67,6 +68,29 @@ DIALOG_EXPORT_2581::DIALOG_EXPORT_2581( PCB_EDIT_FRAME* aParent ) :
 }
 
 
+DIALOG_EXPORT_2581::DIALOG_EXPORT_2581(JOB_EXPORT_PCB_IPC2581* aJob, PCB_EDIT_FRAME* aEditFrame,
+                                        wxWindow* aParent ) :
+        DIALOG_EXPORT_2581_BASE( aParent ),
+        m_parent( aEditFrame ),
+        m_job( aJob )
+{
+    m_browseButton->Hide();
+
+    SetupStandardButtons( { { wxID_OK, _( "Save" ) }, { wxID_CANCEL, _( "Close" ) } } );
+
+    m_outputFileName->SetValue( m_job->GetOutputPath() );
+
+    m_textDistributor->SetSize( m_choiceDistPN->GetSize() );
+
+    // Fill wxChoice (and others) items with data before calling finishDialogSettings()
+    // to calculate suitable widgets sizes
+    Init();
+
+    // Now all widgets have the size fixed, call FinishDialogSettings
+    finishDialogSettings();
+}
+
+
 void DIALOG_EXPORT_2581::onBrowseClicked( wxCommandEvent& event )
 {
     // Build the absolute path of current output directory to preselect it in the file browser.
@@ -88,7 +112,10 @@ void DIALOG_EXPORT_2581::onBrowseClicked( wxCommandEvent& event )
 
 void DIALOG_EXPORT_2581::onOKClick( wxCommandEvent& event )
 {
-    m_parent->SetLastPath( LAST_PATH_2581, m_outputFileName->GetValue() );
+    if( !m_job )
+    {
+        m_parent->SetLastPath( LAST_PATH_2581, m_outputFileName->GetValue() );
+    }
 
     event.Skip();
 }
@@ -226,10 +253,20 @@ bool DIALOG_EXPORT_2581::Init()
             options.insert( field->GetName() );
     }
 
-    m_choiceUnits->SetSelection( cfg->m_Export2581.units );
-    m_precision->SetValue( cfg->m_Export2581.precision );
-    m_versionChoice->SetSelection( cfg->m_Export2581.version );
-    m_cbCompress->SetValue( cfg->m_Export2581.compress );
+    if( !m_job )
+    {
+        m_choiceUnits->SetSelection( cfg->m_Export2581.units );
+        m_precision->SetValue( cfg->m_Export2581.precision );
+        m_versionChoice->SetSelection( cfg->m_Export2581.version );
+        m_cbCompress->SetValue( cfg->m_Export2581.compress );
+    }
+    else
+    {
+        m_choiceUnits->SetSelection( static_cast<int>( m_job->m_units ) );
+        m_precision->SetValue( static_cast<int>( m_job->m_precision ) );
+        m_versionChoice->SetSelection( m_job->m_version == JOB_EXPORT_PCB_IPC2581::IPC2581_VERSION::B ? 0 : 1 );
+        m_cbCompress->SetValue( m_job->m_compress );
+    }
 
     wxCommandEvent dummy;
     onCompressCheck( dummy );
@@ -244,14 +281,37 @@ bool DIALOG_EXPORT_2581::Init()
 
     PROJECT_FILE& prj = Prj().GetProjectFile();
 
-    if( !m_choiceMPN->SetStringSelection( prj.m_IP2581Bom.id ) )
+    wxString internalIdCol;
+    wxString mpnCol;
+    wxString distPnCol;
+    wxString mfgCol;
+    wxString distCol;
+
+    if( !m_job )
+    {
+        internalIdCol = prj.m_IP2581Bom.id;
+		mpnCol = prj.m_IP2581Bom.MPN;
+		distPnCol = prj.m_IP2581Bom.distPN;
+		mfgCol = prj.m_IP2581Bom.mfg;
+		distCol = prj.m_IP2581Bom.dist;
+	}
+	else
+	{
+		internalIdCol = m_job->m_colInternalId;
+		mpnCol = m_job->m_colMfgPn;
+		distPnCol = m_job->m_colDistPn;
+		mfgCol = m_job->m_colMfg;
+		distCol = m_job->m_colDist;
+    }
+
+    if( !m_choiceMPN->SetStringSelection( internalIdCol ) )
         m_choiceMPN->SetSelection( 0 );
 
-    if( m_choiceMPN->SetStringSelection( prj.m_IP2581Bom.MPN ) )
+    if( m_choiceMPN->SetStringSelection( mpnCol ) )
     {
         m_choiceMfg->Enable( true );
 
-        if( !m_choiceMfg->SetStringSelection( prj.m_IP2581Bom.mfg ) )
+        if( !m_choiceMfg->SetStringSelection( mfgCol ) )
             m_choiceMfg->SetSelection( 0 );
     }
     else
@@ -261,14 +321,14 @@ bool DIALOG_EXPORT_2581::Init()
         m_choiceMfg->Enable( false );
     }
 
-    if( m_choiceDistPN->SetStringSelection( prj.m_IP2581Bom.distPN ) )
+    if( m_choiceDistPN->SetStringSelection( distPnCol ) )
     {
         m_textDistributor->Enable( true );
 
         // The combo box selection can be fixed, so any value can be entered
         if( !prj.m_IP2581Bom.distPN.empty() )
         {
-            m_textDistributor->SetValue( prj.m_IP2581Bom.dist );
+            m_textDistributor->SetValue( distCol );
         }
         else
         {
@@ -288,22 +348,43 @@ bool DIALOG_EXPORT_2581::Init()
 
 bool DIALOG_EXPORT_2581::TransferDataFromWindow()
 {
-    PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
+    if( !m_job )
+    {
+        PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
 
-    cfg->m_Export2581.units = m_choiceUnits->GetSelection();
-    cfg->m_Export2581.precision = m_precision->GetValue();
-    cfg->m_Export2581.version = m_versionChoice->GetSelection();
-    cfg->m_Export2581.compress = m_cbCompress->GetValue();
+        cfg->m_Export2581.units = m_choiceUnits->GetSelection();
+        cfg->m_Export2581.precision = m_precision->GetValue();
+        cfg->m_Export2581.version = m_versionChoice->GetSelection();
+        cfg->m_Export2581.compress = m_cbCompress->GetValue();
 
-    PROJECT_FILE& prj = Prj().GetProjectFile();
-    wxString empty;
+        PROJECT_FILE& prj = Prj().GetProjectFile();
+        wxString      empty;
 
-    prj.m_IP2581Bom.id = GetOEM();
-    prj.m_IP2581Bom.mfg = GetMfg();
-    prj.m_IP2581Bom.MPN = GetMPN();
-    prj.m_IP2581Bom.distPN = GetDistPN();
-    prj.m_IP2581Bom.dist = GetDist();
+        prj.m_IP2581Bom.id = GetOEM();
+        prj.m_IP2581Bom.mfg = GetMfg();
+        prj.m_IP2581Bom.MPN = GetMPN();
+        prj.m_IP2581Bom.distPN = GetDistPN();
+        prj.m_IP2581Bom.dist = GetDist();
+
+        s_oemColumn = m_oemRef->GetStringSelection();
+    }
+    else
+    {
+        m_job->SetOutputPath( m_outputFileName->GetValue() );
+
+        m_job->m_colInternalId = GetOEM();
+        m_job->m_colDist = GetDist();
+        m_job->m_colDistPn = GetDistPN();
+        m_job->m_colMfg = GetMfg();
+        m_job->m_colMfgPn = GetMPN();
+
+        m_job->m_version = GetVersion() == 'B' ? JOB_EXPORT_PCB_IPC2581::IPC2581_VERSION::B
+											   : JOB_EXPORT_PCB_IPC2581::IPC2581_VERSION::C;
+        m_job->m_units = GetUnitsString() == wxT( "mm" ) ? JOB_EXPORT_PCB_IPC2581::IPC2581_UNITS::MILLIMETERS
+														  : JOB_EXPORT_PCB_IPC2581::IPC2581_UNITS::INCHES;
+        m_job->m_precision = m_precision->GetValue();
+        m_job->m_compress = GetCompress();
+    }
 
-    s_oemColumn = m_oemRef->GetStringSelection();
     return true;
 }
\ No newline at end of file
diff --git a/pcbnew/dialogs/dialog_export_2581.h b/pcbnew/dialogs/dialog_export_2581.h
index 308778d0ae..3b59974e49 100644
--- a/pcbnew/dialogs/dialog_export_2581.h
+++ b/pcbnew/dialogs/dialog_export_2581.h
@@ -22,11 +22,13 @@
 #include "dialog_export_2581_base.h"
 
 class PCB_EDIT_FRAME;
+class JOB_EXPORT_PCB_IPC2581;
 
 class DIALOG_EXPORT_2581 : public DIALOG_EXPORT_2581_BASE
 {
 public:
     DIALOG_EXPORT_2581( PCB_EDIT_FRAME* aParent );
+    DIALOG_EXPORT_2581( JOB_EXPORT_PCB_IPC2581* aJob, PCB_EDIT_FRAME* aEditFrame, wxWindow* aParent );
 
     wxString GetOutputPath() const
     {
@@ -108,6 +110,7 @@ private:
     bool TransferDataFromWindow() override;
 
     PCB_EDIT_FRAME* m_parent;
+    JOB_EXPORT_PCB_IPC2581* m_job;
 };
 
 #endif // IPC2581_EXPORT_DIALOG_H
\ No newline at end of file
diff --git a/pcbnew/dialogs/dialog_export_step.cpp b/pcbnew/dialogs/dialog_export_step.cpp
index 62d2fc23bb..96b2e34320 100644
--- a/pcbnew/dialogs/dialog_export_step.cpp
+++ b/pcbnew/dialogs/dialog_export_step.cpp
@@ -49,6 +49,7 @@
 #include <filename_resolver.h>
 #include <core/map_helpers.h>
 #include <settings/settings_manager.h>
+#include <jobs/job_export_pcb_3d.h>
 
 
 // Maps m_choiceFormat selection to extension (and kicad-cli command)
@@ -81,16 +82,33 @@ bool DIALOG_EXPORT_STEP::m_fuseShapes = false;
 DIALOG_EXPORT_STEP::COMPONENT_MODE DIALOG_EXPORT_STEP::m_componentMode = COMPONENT_MODE::EXPORT_ALL;
 wxString DIALOG_EXPORT_STEP::m_componentFilter;
 
+
 DIALOG_EXPORT_STEP::DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aEditFrame, const wxString& aBoardPath ) :
-        DIALOG_EXPORT_STEP_BASE( aEditFrame )
+        DIALOG_EXPORT_STEP( aEditFrame, aEditFrame, aBoardPath )
 {
-    m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
+}
 
-    m_editFrame = aEditFrame;
-    m_boardPath = aBoardPath;
 
-    SetupStandardButtons( { { wxID_OK,     _( "Export" ) },
-                            { wxID_CANCEL, _( "Close" )  } } );
+DIALOG_EXPORT_STEP::DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aEditFrame, wxWindow* aParent,
+                                        const wxString&    aBoardPath,
+                                        JOB_EXPORT_PCB_3D* aJob ) :
+        DIALOG_EXPORT_STEP_BASE( aEditFrame ),
+        m_editFrame( aEditFrame ),
+        m_job( aJob ),
+        m_boardPath( aBoardPath )
+{
+    if( m_job == nullptr )
+    {
+        m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
+        SetupStandardButtons( { { wxID_OK,     _( "Export" ) },
+                                { wxID_CANCEL, _( "Close" )  } } );
+    }
+    else
+    {
+        m_browseButton->Hide();
+        SetupStandardButtons( { { wxID_OK,     _( "Save" ) },
+                                { wxID_CANCEL, _( "Close" )  } } );
+    }
 
     // Build default output file name
     // (last saved filename in project or built from board filename)
@@ -110,62 +128,65 @@ DIALOG_EXPORT_STEP::DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aEditFrame, const wxStri
 
     SetFocus();
 
-    PCBNEW_SETTINGS* cfg = m_editFrame->GetPcbNewSettings();
-
-    m_origin = static_cast<STEP_ORIGIN_OPTION>( cfg->m_ExportStep.origin_mode );
-
-    switch( m_origin )
+    if( !m_job )
     {
-    default:
-    case STEP_ORIGIN_PLOT_AXIS:    m_rbDrillAndPlotOrigin->SetValue( true ); break;
-    case STEP_ORIGIN_GRID_AXIS:    m_rbGridOrigin->SetValue( true );         break;
-    case STEP_ORIGIN_USER:         m_rbUserDefinedOrigin->SetValue( true );  break;
-    case STEP_ORIGIN_BOARD_CENTER: m_rbBoardCenterOrigin->SetValue( true );  break;
+        PCBNEW_SETTINGS* cfg = m_editFrame->GetPcbNewSettings();
+
+        m_origin = static_cast<STEP_ORIGIN_OPTION>( cfg->m_ExportStep.origin_mode );
+
+        switch( m_origin )
+        {
+        default:
+        case STEP_ORIGIN_PLOT_AXIS: m_rbDrillAndPlotOrigin->SetValue( true ); break;
+        case STEP_ORIGIN_GRID_AXIS: m_rbGridOrigin->SetValue( true ); break;
+        case STEP_ORIGIN_USER: m_rbUserDefinedOrigin->SetValue( true ); break;
+        case STEP_ORIGIN_BOARD_CENTER: m_rbBoardCenterOrigin->SetValue( true ); break;
+        }
+
+        m_originUnits = cfg->m_ExportStep.origin_units;
+        m_userOriginX = cfg->m_ExportStep.origin_x;
+        m_userOriginY = cfg->m_ExportStep.origin_y;
+        m_noUnspecified = cfg->m_ExportStep.no_unspecified;
+        m_noDNP = cfg->m_ExportStep.no_dnp;
+
+        m_txtNetFilter->SetValue( m_netFilter );
+        m_cbOptimizeStep->SetValue( m_optimizeStep );
+        m_cbExportBody->SetValue( m_exportBoardBody );
+        m_cbExportComponents->SetValue( m_exportComponents );
+        m_cbExportTracks->SetValue( m_exportTracks );
+        m_cbExportPads->SetValue( m_exportPads );
+        m_cbExportZones->SetValue( m_exportZones );
+        m_cbExportInnerCopper->SetValue( m_exportInnerCopper );
+        m_cbExportSilkscreen->SetValue( m_exportSilkscreen );
+        m_cbExportSoldermask->SetValue( m_exportSoldermask );
+        m_cbFuseShapes->SetValue( m_fuseShapes );
+        m_cbRemoveUnspecified->SetValue( m_noUnspecified );
+        m_cbRemoveDNP->SetValue( m_noDNP );
+        m_cbSubstModels->SetValue( cfg->m_ExportStep.replace_models );
+        m_cbOverwriteFile->SetValue( cfg->m_ExportStep.overwrite_file );
+
+        m_txtComponentFilter->SetValue( m_componentFilter );
+
+        switch( m_componentMode )
+        {
+        case COMPONENT_MODE::EXPORT_ALL: m_rbAllComponents->SetValue( true ); break;
+        case COMPONENT_MODE::EXPORT_SELECTED: m_rbOnlySelected->SetValue( true ); break;
+        case COMPONENT_MODE::CUSTOM_FILTER: m_rbFilteredComponents->SetValue( true ); break;
+        }
+
+        // Sync the enabled states
+        wxCommandEvent dummy;
+        DIALOG_EXPORT_STEP::onCbExportComponents( dummy );
+
+        m_STEP_OrgUnitChoice->SetSelection( m_originUnits );
+        wxString tmpStr;
+        tmpStr << m_userOriginX;
+        m_STEP_Xorg->SetValue( tmpStr );
+        tmpStr = wxEmptyString;
+        tmpStr << m_userOriginY;
+        m_STEP_Yorg->SetValue( tmpStr );
     }
 
-    m_originUnits = cfg->m_ExportStep.origin_units;
-    m_userOriginX = cfg->m_ExportStep.origin_x;
-    m_userOriginY = cfg->m_ExportStep.origin_y;
-    m_noUnspecified = cfg->m_ExportStep.no_unspecified;
-    m_noDNP       = cfg->m_ExportStep.no_dnp;
-
-    m_txtNetFilter->SetValue( m_netFilter );
-    m_cbOptimizeStep->SetValue( m_optimizeStep );
-    m_cbExportBody->SetValue( m_exportBoardBody );
-    m_cbExportComponents->SetValue( m_exportComponents );
-    m_cbExportTracks->SetValue( m_exportTracks );
-    m_cbExportPads->SetValue( m_exportPads );
-    m_cbExportZones->SetValue( m_exportZones );
-    m_cbExportInnerCopper->SetValue( m_exportInnerCopper );
-    m_cbExportSilkscreen->SetValue( m_exportSilkscreen );
-    m_cbExportSoldermask->SetValue( m_exportSoldermask );
-    m_cbFuseShapes->SetValue( m_fuseShapes );
-    m_cbRemoveUnspecified->SetValue( m_noUnspecified );
-    m_cbRemoveDNP->SetValue( m_noDNP );
-    m_cbSubstModels->SetValue( cfg->m_ExportStep.replace_models );
-    m_cbOverwriteFile->SetValue( cfg->m_ExportStep.overwrite_file );
-
-    m_txtComponentFilter->SetValue( m_componentFilter );
-
-    switch( m_componentMode )
-    {
-    case COMPONENT_MODE::EXPORT_ALL:      m_rbAllComponents->SetValue( true );      break;
-    case COMPONENT_MODE::EXPORT_SELECTED: m_rbOnlySelected->SetValue( true );       break;
-    case COMPONENT_MODE::CUSTOM_FILTER:   m_rbFilteredComponents->SetValue( true ); break;
-    }
-
-    // Sync the enabled states
-    wxCommandEvent dummy;
-    DIALOG_EXPORT_STEP::onCbExportComponents( dummy );
-
-    m_STEP_OrgUnitChoice->SetSelection( m_originUnits );
-    wxString tmpStr;
-    tmpStr << m_userOriginX;
-    m_STEP_Xorg->SetValue( tmpStr );
-    tmpStr = wxEmptyString;
-    tmpStr << m_userOriginY;
-    m_STEP_Yorg->SetValue( tmpStr );
-
     wxString bad_scales;
     size_t   bad_count = 0;
 
@@ -424,261 +445,324 @@ void DIALOG_EXPORT_STEP::OnComponentModeChange( wxCommandEvent& event )
 
 void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
 {
-    wxString path = m_outputFileName->GetValue();
-    m_editFrame->SetLastPath( LAST_PATH_STEP, path );
-
-    // Build the absolute path of current output directory to preselect it in the file browser.
-    std::function<bool( wxString* )> textResolver =
-            [&]( wxString* token ) -> bool
-            {
-                return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
-            };
-
-    path = ExpandTextVars( path, &textResolver );
-    path = ExpandEnvVarSubstitutions( path, &Prj() );
-    path = Prj().AbsolutePath( path );
-
-    if( path.IsEmpty() )
+    if( !m_job )
     {
-        DisplayErrorMessage( this, _( "No filename for output file" ) );
-        return;
-    }
+        wxString path = m_outputFileName->GetValue();
+        m_editFrame->SetLastPath( LAST_PATH_STEP, path );
 
-    m_netFilter = m_txtNetFilter->GetValue();
-    m_componentFilter = m_txtComponentFilter->GetValue();
+        // Build the absolute path of current output directory to preselect it in the file browser.
+        std::function<bool( wxString* )> textResolver =
+                [&]( wxString* token ) -> bool
+                {
+                    return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
+                };
 
-    if( m_rbAllComponents->GetValue() )
-        m_componentMode = COMPONENT_MODE::EXPORT_ALL;
-    else if( m_rbOnlySelected->GetValue() )
-        m_componentMode = COMPONENT_MODE::EXPORT_SELECTED;
-    else
-        m_componentMode = COMPONENT_MODE::CUSTOM_FILTER;
+        path = ExpandTextVars( path, &textResolver );
+        path = ExpandEnvVarSubstitutions( path, &Prj() );
+        path = Prj().AbsolutePath( path );
 
-    double tolerance;   // default value in mm
-    m_toleranceLastChoice = m_choiceTolerance->GetSelection();
-    m_formatLastChoice = m_choiceFormat->GetSelection();
-    m_optimizeStep = m_cbOptimizeStep->GetValue();
-    m_exportBoardBody = m_cbExportBody->GetValue();
-    m_exportComponents = m_cbExportComponents->GetValue();
-    m_exportTracks = m_cbExportTracks->GetValue();
-    m_exportPads = m_cbExportPads->GetValue();
-    m_exportZones = m_cbExportZones->GetValue();
-    m_exportInnerCopper = m_cbExportInnerCopper->GetValue();
-    m_exportSilkscreen = m_cbExportSilkscreen->GetValue();
-    m_exportSoldermask = m_cbExportSoldermask->GetValue();
-    m_fuseShapes = m_cbFuseShapes->GetValue();
-
-    switch( m_choiceTolerance->GetSelection() )
-    {
-    case 0:  tolerance = 0.001; break;
-    default:
-    case 1:  tolerance = 0.01;  break;
-    case 2:  tolerance = 0.1;   break;
-    }
-
-    SHAPE_POLY_SET outline;
-    wxString msg;
-
-    // Check if the board outline is continuous
-    // max dist from one endPt to next startPt to build a closed shape:
-    int chainingEpsilon = pcbIUScale.mmToIU( tolerance );
-
-    // Arc to segment approx error (not critical here: we do not use the outline shape):
-    int maxError = pcbIUScale.mmToIU( 0.005 );
-    bool success = BuildBoardPolygonOutlines( m_editFrame->GetBoard(), outline, maxError,
-                                              chainingEpsilon, nullptr );
-    if( !success )
-    {
-        DisplayErrorMessage( this, wxString::Format(
-                             _( "Board outline is missing or not closed using %.3f mm tolerance.\n"
-                                "Run DRC for a full analysis." ), tolerance ) );
-        return;
-    }
-
-    wxFileName fn( Prj().AbsolutePath( path ) );
-
-    if( fn.FileExists() && !GetOverwriteFile() )
-    {
-        msg.Printf( _( "File '%s' already exists. Do you want overwrite this file?" ),
-                    fn.GetFullPath() );
-
-        if( wxMessageBox( msg, _( "STEP/GLTF Export" ), wxYES_NO | wxICON_QUESTION, this ) == wxNO )
-            return;
-    }
-
-    wxFileName appK2S( wxStandardPaths::Get().GetExecutablePath() );
-#ifdef __WXMAC__
-    // On macOS, we have standalone applications inside the main bundle, so we handle that here:
-    if( appK2S.GetPath().Find( "/Contents/Applications/pcbnew.app/Contents/MacOS" ) != wxNOT_FOUND )
-    {
-        appK2S.AppendDir( wxT( ".." ) );
-        appK2S.AppendDir( wxT( ".." ) );
-        appK2S.AppendDir( wxT( ".." ) );
-        appK2S.AppendDir( wxT( ".." ) );
-        appK2S.AppendDir( wxT( "MacOS" ) );
-    }
-#else
-    if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
-    {
-        appK2S.RemoveLastDir();
-        appK2S.AppendDir( "kicad" );
-    }
-#endif
-
-    appK2S.SetName( wxT( "kicad-cli" ) );
-    appK2S.Normalize( FN_NORMALIZE_FLAGS );
-
-    wxString cmdK2S = wxT( "\"" );
-    cmdK2S.Append( appK2S.GetFullPath() );
-    cmdK2S.Append( wxT( "\"" ) );
-
-    cmdK2S.Append( wxT( " pcb" ) );
-    cmdK2S.Append( wxT( " export" ) );
-
-    cmdK2S.Append( wxT( " " ) );
-    cmdK2S.Append( c_formatCommand[m_choiceFormat->GetSelection()] );
-
-    if( GetNoUnspecifiedOption() )
-        cmdK2S.Append( wxT( " --no-unspecified" ) );
-
-    if( GetNoDNPOption() )
-        cmdK2S.Append( wxT( " --no-dnp" ) );
-
-    if( GetSubstOption() )
-        cmdK2S.Append( wxT( " --subst-models" ) );
-
-    if( !m_optimizeStep )
-        cmdK2S.Append( wxT( " --no-optimize-step" ) );
-
-    if( !m_exportBoardBody )
-        cmdK2S.Append( wxT( " --no-board-body" ) );
-
-    if( !m_exportComponents )
-        cmdK2S.Append( wxT( " --no-components" ) );
-
-    if( m_exportTracks )
-        cmdK2S.Append( wxT( " --include-tracks" ) );
-
-    if( m_exportPads )
-        cmdK2S.Append( wxT( " --include-pads" ) );
-
-    if( m_exportZones )
-        cmdK2S.Append( wxT( " --include-zones" ) );
-
-    if( m_exportInnerCopper )
-        cmdK2S.Append( wxT( " --include-inner-copper" ) );
-
-    if( m_exportSilkscreen )
-        cmdK2S.Append( wxT( " --include-silkscreen" ) );
-
-    if( m_exportSoldermask )
-        cmdK2S.Append( wxT( " --include-soldermask" ) );
-
-    if( m_fuseShapes )
-        cmdK2S.Append( wxT( " --fuse-shapes" ) );
-
-    // Note: for some reason, using \" to insert a quote in a format string, under MacOS
-    // wxString::Format does not work. So use a %c format in string
-    int quote = '\'';
-    int dblquote = '"';
-
-    if( !m_netFilter.empty() )
-    {
-        cmdK2S.Append( wxString::Format( wxT( " --net-filter %c%s%c" ), dblquote, m_netFilter,
-                                         dblquote ) );
-    }
-
-    switch( m_componentMode )
-    {
-    case COMPONENT_MODE::EXPORT_SELECTED:
-    {
-        wxArrayString components;
-        SELECTION& selection = m_editFrame->GetCurrentSelection();
-
-        std::for_each( selection.begin(), selection.end(),
-                       [&components]( EDA_ITEM* item )
-                       {
-                           if( item->Type() == PCB_FOOTPRINT_T )
-                               components.push_back( static_cast<FOOTPRINT*>( item )->GetReference() );
-                       } );
-
-        cmdK2S.Append( wxString::Format( wxT( " --component-filter %c%s%c" ), dblquote,
-                                         wxJoin( components, ',' ), dblquote ) );
-        break;
-    }
-
-    case COMPONENT_MODE::CUSTOM_FILTER:
-        cmdK2S.Append( wxString::Format( wxT( " --component-filter %c%s%c" ), dblquote,
-                                         m_componentFilter, dblquote ) );
-        break;
-
-    default:
-        break;
-    }
-
-    switch( GetOriginOption() )
-    {
-    case STEP_ORIGIN_0:
-        wxFAIL_MSG( wxT( "Unsupported origin option: how did we get here?" ) );
-        break;
-
-    case STEP_ORIGIN_PLOT_AXIS:
-        cmdK2S.Append( wxT( " --drill-origin" ) );
-        break;
-
-    case STEP_ORIGIN_GRID_AXIS:
-        cmdK2S.Append( wxT( " --grid-origin" ) );
-        break;
-
-    case STEP_ORIGIN_USER:
-    {
-        double xOrg = GetXOrg();
-        double yOrg = GetYOrg();
-
-        if( GetOrgUnitsChoice() == 1 )
+        if( path.IsEmpty() )
         {
-            // selected reference unit is in inches, and STEP units are mm
-            xOrg *= 25.4;
-            yOrg *= 25.4;
+            DisplayErrorMessage( this, _( "No filename for output file" ) );
+            return;
         }
 
-        LOCALE_IO dummy;
-        cmdK2S.Append( wxString::Format( wxT( " --user-origin=%c%.6fx%.6fmm%c" ),
-                                         quote, xOrg, yOrg, quote ) );
-        break;
-    }
+        m_netFilter = m_txtNetFilter->GetValue();
+        m_componentFilter = m_txtComponentFilter->GetValue();
 
-    case STEP_ORIGIN_BOARD_CENTER:
+        if( m_rbAllComponents->GetValue() )
+            m_componentMode = COMPONENT_MODE::EXPORT_ALL;
+        else if( m_rbOnlySelected->GetValue() )
+            m_componentMode = COMPONENT_MODE::EXPORT_SELECTED;
+        else
+            m_componentMode = COMPONENT_MODE::CUSTOM_FILTER;
+
+        double tolerance;   // default value in mm
+        m_toleranceLastChoice = m_choiceTolerance->GetSelection();
+        m_formatLastChoice = m_choiceFormat->GetSelection();
+        m_optimizeStep = m_cbOptimizeStep->GetValue();
+        m_exportBoardBody = m_cbExportBody->GetValue();
+        m_exportComponents = m_cbExportComponents->GetValue();
+        m_exportTracks = m_cbExportTracks->GetValue();
+        m_exportPads = m_cbExportPads->GetValue();
+        m_exportZones = m_cbExportZones->GetValue();
+        m_exportInnerCopper = m_cbExportInnerCopper->GetValue();
+        m_exportSilkscreen = m_cbExportSilkscreen->GetValue();
+        m_exportSoldermask = m_cbExportSoldermask->GetValue();
+        m_fuseShapes = m_cbFuseShapes->GetValue();
+
+        switch( m_choiceTolerance->GetSelection() )
+        {
+        case 0:  tolerance = 0.001; break;
+        default:
+        case 1:  tolerance = 0.01;  break;
+        case 2:  tolerance = 0.1;   break;
+        }
+
+        SHAPE_POLY_SET outline;
+        wxString msg;
+
+        // Check if the board outline is continuous
+        // max dist from one endPt to next startPt to build a closed shape:
+        int chainingEpsilon = pcbIUScale.mmToIU( tolerance );
+
+        // Arc to segment approx error (not critical here: we do not use the outline shape):
+        int maxError = pcbIUScale.mmToIU( 0.005 );
+        bool success = BuildBoardPolygonOutlines( m_editFrame->GetBoard(), outline, maxError,
+                                                  chainingEpsilon, nullptr );
+        if( !success )
+        {
+            DisplayErrorMessage( this, wxString::Format(
+                                 _( "Board outline is missing or not closed using %.3f mm tolerance.\n"
+                                    "Run DRC for a full analysis." ), tolerance ) );
+            return;
+        }
+
+        wxFileName fn( Prj().AbsolutePath( path ) );
+
+        if( fn.FileExists() && !GetOverwriteFile() )
+        {
+            msg.Printf( _( "File '%s' already exists. Do you want overwrite this file?" ),
+                        fn.GetFullPath() );
+
+            if( wxMessageBox( msg, _( "STEP/GLTF Export" ), wxYES_NO | wxICON_QUESTION, this ) == wxNO )
+                return;
+        }
+
+        wxFileName appK2S( wxStandardPaths::Get().GetExecutablePath() );
+    #ifdef __WXMAC__
+        // On macOS, we have standalone applications inside the main bundle, so we handle that here:
+        if( appK2S.GetPath().Find( "/Contents/Applications/pcbnew.app/Contents/MacOS" ) != wxNOT_FOUND )
+        {
+            appK2S.AppendDir( wxT( ".." ) );
+            appK2S.AppendDir( wxT( ".." ) );
+            appK2S.AppendDir( wxT( ".." ) );
+            appK2S.AppendDir( wxT( ".." ) );
+            appK2S.AppendDir( wxT( "MacOS" ) );
+        }
+    #else
+        if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
+        {
+            appK2S.RemoveLastDir();
+            appK2S.AppendDir( "kicad" );
+        }
+    #endif
+
+        appK2S.SetName( wxT( "kicad-cli" ) );
+        appK2S.Normalize( FN_NORMALIZE_FLAGS );
+
+        wxString cmdK2S = wxT( "\"" );
+        cmdK2S.Append( appK2S.GetFullPath() );
+        cmdK2S.Append( wxT( "\"" ) );
+
+        cmdK2S.Append( wxT( " pcb" ) );
+        cmdK2S.Append( wxT( " export" ) );
+
+        cmdK2S.Append( wxT( " " ) );
+        cmdK2S.Append( c_formatCommand[m_choiceFormat->GetSelection()] );
+
+        if( GetNoUnspecifiedOption() )
+            cmdK2S.Append( wxT( " --no-unspecified" ) );
+
+        if( GetNoDNPOption() )
+            cmdK2S.Append( wxT( " --no-dnp" ) );
+
+        if( GetSubstOption() )
+            cmdK2S.Append( wxT( " --subst-models" ) );
+
+        if( !m_optimizeStep )
+            cmdK2S.Append( wxT( " --no-optimize-step" ) );
+
+        if( !m_exportBoardBody )
+            cmdK2S.Append( wxT( " --no-board-body" ) );
+
+        if( !m_exportComponents )
+            cmdK2S.Append( wxT( " --no-components" ) );
+
+        if( m_exportTracks )
+            cmdK2S.Append( wxT( " --include-tracks" ) );
+
+        if( m_exportPads )
+            cmdK2S.Append( wxT( " --include-pads" ) );
+
+        if( m_exportZones )
+            cmdK2S.Append( wxT( " --include-zones" ) );
+
+        if( m_exportInnerCopper )
+            cmdK2S.Append( wxT( " --include-inner-copper" ) );
+
+        if( m_exportSilkscreen )
+            cmdK2S.Append( wxT( " --include-silkscreen" ) );
+
+        if( m_exportSoldermask )
+            cmdK2S.Append( wxT( " --include-soldermask" ) );
+
+        if( m_fuseShapes )
+            cmdK2S.Append( wxT( " --fuse-shapes" ) );
+
+        // Note: for some reason, using \" to insert a quote in a format string, under MacOS
+        // wxString::Format does not work. So use a %c format in string
+        int quote = '\'';
+        int dblquote = '"';
+
+        if( !m_netFilter.empty() )
+        {
+            cmdK2S.Append( wxString::Format( wxT( " --net-filter %c%s%c" ), dblquote, m_netFilter,
+                                             dblquote ) );
+        }
+
+        switch( m_componentMode )
+        {
+        case COMPONENT_MODE::EXPORT_SELECTED:
+        {
+            wxArrayString components;
+            SELECTION& selection = m_editFrame->GetCurrentSelection();
+
+            std::for_each( selection.begin(), selection.end(),
+                           [&components]( EDA_ITEM* item )
+                           {
+                               if( item->Type() == PCB_FOOTPRINT_T )
+                                   components.push_back( static_cast<FOOTPRINT*>( item )->GetReference() );
+                           } );
+
+            cmdK2S.Append( wxString::Format( wxT( " --component-filter %c%s%c" ), dblquote,
+                                             wxJoin( components, ',' ), dblquote ) );
+            break;
+        }
+
+        case COMPONENT_MODE::CUSTOM_FILTER:
+            cmdK2S.Append( wxString::Format( wxT( " --component-filter %c%s%c" ), dblquote,
+                                             m_componentFilter, dblquote ) );
+            break;
+
+        default:
+            break;
+        }
+
+        switch( GetOriginOption() )
+        {
+        case STEP_ORIGIN_0:
+            wxFAIL_MSG( wxT( "Unsupported origin option: how did we get here?" ) );
+            break;
+
+        case STEP_ORIGIN_PLOT_AXIS:
+            cmdK2S.Append( wxT( " --drill-origin" ) );
+            break;
+
+        case STEP_ORIGIN_GRID_AXIS:
+            cmdK2S.Append( wxT( " --grid-origin" ) );
+            break;
+
+        case STEP_ORIGIN_USER:
+        {
+            double xOrg = GetXOrg();
+            double yOrg = GetYOrg();
+
+            if( GetOrgUnitsChoice() == 1 )
+            {
+                // selected reference unit is in inches, and STEP units are mm
+                xOrg *= 25.4;
+                yOrg *= 25.4;
+            }
+
+            LOCALE_IO dummy;
+            cmdK2S.Append( wxString::Format( wxT( " --user-origin=%c%.6fx%.6fmm%c" ),
+                                             quote, xOrg, yOrg, quote ) );
+            break;
+        }
+
+        case STEP_ORIGIN_BOARD_CENTER:
+        {
+            BOX2I     bbox = m_editFrame->GetBoard()->ComputeBoundingBox( true );
+            double    xOrg = pcbIUScale.IUTomm( bbox.GetCenter().x );
+            double    yOrg = pcbIUScale.IUTomm( bbox.GetCenter().y );
+            LOCALE_IO dummy;
+
+            cmdK2S.Append( wxString::Format( wxT( " --user-origin=%c%.6fx%.6fmm%c" ),
+                                             quote, xOrg, yOrg, quote ) );
+            break;
+        }
+        }
+
+        {
+            LOCALE_IO dummy;
+            cmdK2S.Append( wxString::Format( wxT( " --min-distance=%c%.3fmm%c" ),
+                                             quote, tolerance, quote ) );
+        }
+
+        // Output file path.
+        cmdK2S.Append( wxString::Format( wxT( " -f -o %c%s%c" ),
+                                         dblquote, fn.GetFullPath(), dblquote ) );
+
+
+        // Input file path.
+        cmdK2S.Append( wxString::Format( wxT( " %c%s%c" ), dblquote, m_boardPath, dblquote ) );
+
+        wxLogTrace( traceKiCad2Step, wxT( "export step command: %s" ), cmdK2S );
+
+        DIALOG_EXPORT_STEP_LOG* log = new DIALOG_EXPORT_STEP_LOG( this, cmdK2S );
+        log->ShowModal();
+    }
+    else
     {
-        BOX2I     bbox = m_editFrame->GetBoard()->ComputeBoundingBox( true );
-        double    xOrg = pcbIUScale.IUTomm( bbox.GetCenter().x );
-        double    yOrg = pcbIUScale.IUTomm( bbox.GetCenter().y );
-        LOCALE_IO dummy;
+        m_job->SetOutputPath( 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();
+        m_job->m_3dparams.m_ExportComponents = m_cbExportComponents->GetValue();
+        m_job->m_3dparams.m_ExportTracksVias = m_cbExportTracks->GetValue();
+        m_job->m_3dparams.m_ExportPads = m_cbExportPads->GetValue();
+        m_job->m_3dparams.m_ExportZones = m_cbExportZones->GetValue();
+        m_job->m_3dparams.m_ExportInnerCopper = m_cbExportInnerCopper->GetValue();
+        m_job->m_3dparams.m_ExportSilkscreen = m_cbExportSilkscreen->GetValue();
+        m_job->m_3dparams.m_ExportSoldermask = m_cbExportSoldermask->GetValue();
+        m_job->m_3dparams.m_FuseShapes = m_cbFuseShapes->GetValue();
+        m_job->m_3dparams.m_OptimizeStep = m_cbOptimizeStep->GetValue();
+        m_job->m_3dparams.m_Format = static_cast<EXPORTER_STEP_PARAMS::FORMAT>( m_choiceFormat->GetSelection() );
+        m_job->m_3dparams.m_Overwrite = m_cbOverwriteFile->GetValue();
+        m_job->m_3dparams.m_IncludeUnspecified = !m_cbRemoveUnspecified->GetValue();
+        m_job->m_3dparams.m_IncludeDNP = !m_cbRemoveDNP->GetValue();
+        m_job->m_3dparams.m_SubstModels = m_cbSubstModels->GetValue();
+
+        switch( GetOriginOption() )
+        {
+        case STEP_ORIGIN_0:
+            break;
+        case STEP_ORIGIN_PLOT_AXIS:
+            m_job->m_3dparams.m_UseDrillOrigin = true;
+            break;
+        case STEP_ORIGIN_GRID_AXIS:
+            m_job->m_3dparams.m_UseGridOrigin = true;
+            break;
+        case STEP_ORIGIN_USER:
+        {
+            double xOrg = GetXOrg();
+            double yOrg = GetYOrg();
+
+            if( GetOrgUnitsChoice() == 1 )
+            {
+                // selected reference unit is in inches, and STEP units are mm
+                xOrg *= 25.4;
+                yOrg *= 25.4;
+            }
+
+            m_job->m_3dparams.m_Origin = VECTOR2D( xOrg, yOrg );
+            break;
+        }
+
+        case STEP_ORIGIN_BOARD_CENTER:
+        {
+            BOX2I     bbox = m_editFrame->GetBoard()->ComputeBoundingBox( true );
+            double    xOrg = pcbIUScale.IUTomm( bbox.GetCenter().x );
+            double    yOrg = pcbIUScale.IUTomm( bbox.GetCenter().y );
+            LOCALE_IO dummy;
+
+            m_job->m_3dparams.m_Origin = VECTOR2D( xOrg, yOrg );
+            break;
+        }
+        }
 
-        cmdK2S.Append( wxString::Format( wxT( " --user-origin=%c%.6fx%.6fmm%c" ),
-                                         quote, xOrg, yOrg, quote ) );
-        break;
     }
-    }
-
-    {
-        LOCALE_IO dummy;
-        cmdK2S.Append( wxString::Format( wxT( " --min-distance=%c%.3fmm%c" ),
-                                         quote, tolerance, quote ) );
-    }
-
-    // Output file path.
-    cmdK2S.Append( wxString::Format( wxT( " -f -o %c%s%c" ),
-                                     dblquote, fn.GetFullPath(), dblquote ) );
-
-
-    // Input file path.
-    cmdK2S.Append( wxString::Format( wxT( " %c%s%c" ), dblquote, m_boardPath, dblquote ) );
-
-    wxLogTrace( traceKiCad2Step, wxT( "export step command: %s" ), cmdK2S );
-
-    DIALOG_EXPORT_STEP_LOG* log = new DIALOG_EXPORT_STEP_LOG( this, cmdK2S );
-    log->ShowModal();
 }
 
 
diff --git a/pcbnew/dialogs/dialog_export_step.h b/pcbnew/dialogs/dialog_export_step.h
index ff1ca89769..290414cc53 100644
--- a/pcbnew/dialogs/dialog_export_step.h
+++ b/pcbnew/dialogs/dialog_export_step.h
@@ -27,6 +27,7 @@
 #include "dialog_export_step_base.h"
 
 class PCB_EDIT_FRAME;
+class JOB_EXPORT_PCB_3D;
 
 class DIALOG_EXPORT_STEP : public DIALOG_EXPORT_STEP_BASE
 {
@@ -41,6 +42,8 @@ public:
     };
 
     DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aEditFrame, const wxString& aBoardPath );
+    DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aEditFrame, wxWindow* aParent, const wxString& aBoardPath,
+                        JOB_EXPORT_PCB_3D* aJob = nullptr );
     ~DIALOG_EXPORT_STEP();
 
 protected:
@@ -96,6 +99,7 @@ private:
     };
 
     PCB_EDIT_FRAME*    m_editFrame;
+    JOB_EXPORT_PCB_3D* m_job;
     STEP_ORIGIN_OPTION m_origin;         // The last preference for STEP origin option
     double             m_userOriginX;    // remember last User Origin X value
     double             m_userOriginY;    // remember last User Origin Y value
diff --git a/pcbnew/dialogs/dialog_export_svg.cpp b/pcbnew/dialogs/dialog_export_svg.cpp
index 2640e6ac49..c1e4d7f315 100644
--- a/pcbnew/dialogs/dialog_export_svg.cpp
+++ b/pcbnew/dialogs/dialog_export_svg.cpp
@@ -41,10 +41,11 @@
 #include <pgm_base.h>
 #include <project/project_file.h>
 #include <exporters/export_svg.h>
+#include <jobs/job_export_pcb_svg.h>
 
 
-DIALOG_EXPORT_SVG::DIALOG_EXPORT_SVG( PCB_EDIT_FRAME* aEditFrame, BOARD* aBoard ) :
-        DIALOG_EXPORT_SVG_BASE( aEditFrame ),
+DIALOG_EXPORT_SVG::DIALOG_EXPORT_SVG( PCB_EDIT_FRAME* aEditFrame, BOARD* aBoard, wxWindow* aParent ) :
+        DIALOG_EXPORT_SVG_BASE( aParent ),
         m_board( aBoard ),
         m_editFrame( aEditFrame ),
         m_printBW( false ),
@@ -78,6 +79,17 @@ DIALOG_EXPORT_SVG::DIALOG_EXPORT_SVG( PCB_EDIT_FRAME* aEditFrame, BOARD* aBoard
 }
 
 
+DIALOG_EXPORT_SVG::DIALOG_EXPORT_SVG( JOB_EXPORT_PCB_SVG* aJob, PCB_EDIT_FRAME* aEditFrame,
+                                      wxWindow* aParent ) :
+        DIALOG_EXPORT_SVG( aEditFrame, aEditFrame->GetBoard(), aParent )
+{
+    m_job = aJob;
+
+    SetupStandardButtons( { { wxID_OK, _( "Save" ) },
+                            { wxID_CANCEL, _( "Close" ) } } );
+}
+
+
 DIALOG_EXPORT_SVG::~DIALOG_EXPORT_SVG()
 {
     m_printBW = m_ModeColorOption->GetSelection();
@@ -350,7 +362,7 @@ void DIALOG_EXPORT_SVG::OnButtonPlot( wxCommandEvent& event )
 
 bool InvokeExportSVG( PCB_EDIT_FRAME* aCaller, BOARD* aBoard )
 {
-    DIALOG_EXPORT_SVG dlg( aCaller, aBoard );
+    DIALOG_EXPORT_SVG dlg( aCaller, aBoard, aCaller );
 
     dlg.ShowModal();
 
diff --git a/pcbnew/dialogs/dialog_export_svg.h b/pcbnew/dialogs/dialog_export_svg.h
index 6fad0b089b..4b0b6c7bec 100644
--- a/pcbnew/dialogs/dialog_export_svg.h
+++ b/pcbnew/dialogs/dialog_export_svg.h
@@ -29,17 +29,20 @@
 
 class BOARD;
 class PCB_EDIT_FRAME;
+class JOB_EXPORT_PCB_SVG;
 
 class DIALOG_EXPORT_SVG : public DIALOG_EXPORT_SVG_BASE
 {
 public:
-    DIALOG_EXPORT_SVG( PCB_EDIT_FRAME* aEditFrame, BOARD* aBoard );
+    DIALOG_EXPORT_SVG( JOB_EXPORT_PCB_SVG* aJob, PCB_EDIT_FRAME* aEditFrame, wxWindow* aParent );
+    DIALOG_EXPORT_SVG( PCB_EDIT_FRAME* aEditFrame, BOARD* aBoard, wxWindow* aParent );
     ~DIALOG_EXPORT_SVG() override;
 
 private:
-    BOARD*          m_board;
-    PCB_EDIT_FRAME* m_editFrame;
-    LSEQ            m_printMaskLayer;
+    BOARD*              m_board;
+    JOB_EXPORT_PCB_SVG* m_job;
+    PCB_EDIT_FRAME*     m_editFrame;
+    LSEQ                m_printMaskLayer;
     // the list of existing board layers in wxCheckListBox, with the
     // board layers id:
     std::pair<wxCheckListBox*, int> m_boxSelectLayer[PCB_LAYER_ID_COUNT];
diff --git a/pcbnew/dialogs/dialog_gen_footprint_position.cpp b/pcbnew/dialogs/dialog_gen_footprint_position.cpp
index 10ddd915d1..3aa1ff6056 100644
--- a/pcbnew/dialogs/dialog_gen_footprint_position.cpp
+++ b/pcbnew/dialogs/dialog_gen_footprint_position.cpp
@@ -40,6 +40,7 @@
 #include <widgets/std_bitmap_button.h>
 #include <exporters/place_file_exporter.h>
 #include "gerber_placefile_writer.h"
+#include <jobs/job_export_pcb_pos.h>
 
 #include <wx/dirdlg.h>
 #include <wx/msgdlg.h>
@@ -61,30 +62,74 @@ DIALOG_GEN_FOOTPRINT_POSITION::DIALOG_GEN_FOOTPRINT_POSITION( PCB_EDIT_FRAME* aE
 }
 
 
+
+DIALOG_GEN_FOOTPRINT_POSITION::DIALOG_GEN_FOOTPRINT_POSITION( JOB_EXPORT_PCB_POS* aJob,
+                                                              PCB_EDIT_FRAME*     aEditFrame,
+                                                              wxWindow*           aParent ) :
+        DIALOG_GEN_FOOTPRINT_POSITION_BASE( aParent ),
+        m_editFrame( aEditFrame ),
+        m_job( aJob )
+{
+    m_messagesPanel->Hide();
+    initDialog();
+
+    SetupStandardButtons( { { wxID_OK, _( "Save" ) }, { wxID_CANCEL, _( "Close" ) } } );
+
+    GetSizer()->SetSizeHints( this );
+    Centre();
+}
+
+
 void DIALOG_GEN_FOOTPRINT_POSITION::initDialog()
 {
-    m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
+    if( !m_job )
+    {
+        m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
 
-    PROJECT_FILE&    projectFile = m_editFrame->Prj().GetProjectFile();
-    PCBNEW_SETTINGS* cfg = m_editFrame->GetPcbNewSettings();
+        PROJECT_FILE&    projectFile = m_editFrame->Prj().GetProjectFile();
+        PCBNEW_SETTINGS* cfg = m_editFrame->GetPcbNewSettings();
 
-    m_units = cfg->m_PlaceFile.units == 0 ? EDA_UNITS::INCHES : EDA_UNITS::MILLIMETRES;
+        m_units = cfg->m_PlaceFile.units == 0 ? EDA_UNITS::INCHES : EDA_UNITS::MILLIMETRES;
 
-    // Output directory
-    m_outputDirectoryName->SetValue( projectFile.m_PcbLastPath[ LAST_PATH_POS_FILES ] );
+        // Output directory
+        m_outputDirectoryName->SetValue( projectFile.m_PcbLastPath[LAST_PATH_POS_FILES] );
+
+        // Update Options
+        m_radioBoxUnits->SetSelection( cfg->m_PlaceFile.units );
+        m_radioBoxFilesCount->SetSelection( cfg->m_PlaceFile.file_options );
+        m_rbFormat->SetSelection( cfg->m_PlaceFile.file_format );
+        m_cbIncludeBoardEdge->SetValue( cfg->m_PlaceFile.include_board_edge );
+        m_useDrillPlaceOrigin->SetValue( cfg->m_PlaceFile.use_aux_origin );
+        m_onlySMD->SetValue( cfg->m_PlaceFile.only_SMD );
+        m_negateXcb->SetValue( cfg->m_PlaceFile.negate_xcoord );
+        m_excludeTH->SetValue( cfg->m_PlaceFile.exclude_TH );
+
+        // Update sizes and sizers:
+        m_messagesPanel->MsgPanelSetMinSize( wxSize( -1, 160 ) );
+    }
+    else
+    {
+        m_browseButton->Hide();
+
+        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_radioBoxUnits->SetSelection( static_cast<int>( m_job->m_units ) );
+        m_radioBoxFilesCount->SetSelection( 0 );
+        m_rbFormat->SetSelection( static_cast<int>( m_job->m_format ) );
+        m_cbIncludeBoardEdge->SetValue( m_job->m_gerberBoardEdge );
+		m_useDrillPlaceOrigin->SetValue( m_job->m_useDrillPlaceFileOrigin );
+        m_onlySMD->SetValue( m_job->m_smdOnly );
+        m_negateXcb->SetValue( m_job->m_negateBottomX );
+        m_excludeTH->SetValue( m_job->m_excludeFootprintsWithTh );
+
+        m_messagesPanel->Hide();
+    }
 
-    // Update Options
-    m_radioBoxUnits->SetSelection( cfg->m_PlaceFile.units );
-    m_radioBoxFilesCount->SetSelection( cfg->m_PlaceFile.file_options );
-    m_rbFormat->SetSelection( cfg->m_PlaceFile.file_format );
-    m_cbIncludeBoardEdge->SetValue( cfg->m_PlaceFile.include_board_edge );
-    m_useDrillPlaceOrigin->SetValue( cfg->m_PlaceFile.use_aux_origin );
-    m_onlySMD->SetValue( cfg->m_PlaceFile.only_SMD );
-    m_negateXcb->SetValue( cfg->m_PlaceFile.negate_xcoord );
-    m_excludeTH->SetValue( cfg->m_PlaceFile.exclude_TH );
 
-    // Update sizes and sizers:
-    m_messagesPanel->MsgPanelSetMinSize( wxSize( -1, 160 ) );
     GetSizer()->SetSizeHints( this );
 }
 
@@ -212,29 +257,48 @@ void DIALOG_GEN_FOOTPRINT_POSITION::OnOutputDirectoryBrowseClicked( wxCommandEve
 
 void DIALOG_GEN_FOOTPRINT_POSITION::OnGenerate( wxCommandEvent& event )
 {
-    m_units  = m_radioBoxUnits->GetSelection() == 0 ? EDA_UNITS::INCHES : EDA_UNITS::MILLIMETRES;
+    if( !m_job )
+    {
+        m_units  = m_radioBoxUnits->GetSelection() == 0 ? EDA_UNITS::INCHES : EDA_UNITS::MILLIMETRES;
 
-    PCBNEW_SETTINGS* cfg = m_editFrame->GetPcbNewSettings();
+        PCBNEW_SETTINGS* cfg = m_editFrame->GetPcbNewSettings();
 
-    wxString dirStr = m_outputDirectoryName->GetValue();
-    // Keep unix directory format convention in cfg files
-    dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
+        wxString dirStr = m_outputDirectoryName->GetValue();
+        // Keep unix directory format convention in cfg files
+        dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
 
-    m_editFrame->Prj().GetProjectFile().m_PcbLastPath[LAST_PATH_POS_FILES] = dirStr;
-    cfg->m_PlaceFile.output_directory   = dirStr;
-    cfg->m_PlaceFile.units              = m_units == EDA_UNITS::INCHES ? 0 : 1;
-    cfg->m_PlaceFile.file_options       = m_radioBoxFilesCount->GetSelection();
-    cfg->m_PlaceFile.file_format        = m_rbFormat->GetSelection();
-    cfg->m_PlaceFile.include_board_edge = m_cbIncludeBoardEdge->GetValue();
-    cfg->m_PlaceFile.exclude_TH         = m_excludeTH->GetValue();
-    cfg->m_PlaceFile.only_SMD           = m_onlySMD->GetValue();
-    cfg->m_PlaceFile.use_aux_origin     = m_useDrillPlaceOrigin->GetValue();
-    cfg->m_PlaceFile.negate_xcoord      = m_negateXcb->GetValue();
+        m_editFrame->Prj().GetProjectFile().m_PcbLastPath[LAST_PATH_POS_FILES] = dirStr;
+        cfg->m_PlaceFile.output_directory   = dirStr;
+        cfg->m_PlaceFile.units              = m_units == EDA_UNITS::INCHES ? 0 : 1;
+        cfg->m_PlaceFile.file_options       = m_radioBoxFilesCount->GetSelection();
+        cfg->m_PlaceFile.file_format        = m_rbFormat->GetSelection();
+        cfg->m_PlaceFile.include_board_edge = m_cbIncludeBoardEdge->GetValue();
+        cfg->m_PlaceFile.exclude_TH         = m_excludeTH->GetValue();
+        cfg->m_PlaceFile.only_SMD           = m_onlySMD->GetValue();
+        cfg->m_PlaceFile.use_aux_origin     = m_useDrillPlaceOrigin->GetValue();
+        cfg->m_PlaceFile.negate_xcoord      = m_negateXcb->GetValue();
 
-    if( m_rbFormat->GetSelection() == 2 )
-        CreateGerberFiles();
+        if( m_rbFormat->GetSelection() == 2 )
+            CreateGerberFiles();
+        else
+            CreateAsciiFiles();
+    }
     else
-        CreateAsciiFiles();
+    {
+        m_job->SetOutputPath( m_outputDirectoryName->GetValue() );
+        m_job->m_units = m_radioBoxUnits->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_rbFormat->GetSelection() );
+        m_job->m_gerberBoardEdge = m_cbIncludeBoardEdge->GetValue();
+        m_job->m_excludeFootprintsWithTh = m_excludeTH->GetValue();
+        m_job->m_smdOnly = m_onlySMD->GetValue();
+        m_job->m_useDrillPlaceFileOrigin = m_useDrillPlaceOrigin->GetValue();
+        m_job->m_negateBottomX = m_negateXcb->GetValue();
+        m_job->m_excludeDNP = m_excludeDNP->GetValue();
+
+        Close();
+    }
 }
 
 
diff --git a/pcbnew/dialogs/dialog_gen_footprint_position.h b/pcbnew/dialogs/dialog_gen_footprint_position.h
index 3816af7bd9..74f2a94d22 100644
--- a/pcbnew/dialogs/dialog_gen_footprint_position.h
+++ b/pcbnew/dialogs/dialog_gen_footprint_position.h
@@ -27,6 +27,7 @@
 
 class PCB_EDIT_FRAME;
 class REPORTER;
+class JOB_EXPORT_PCB_POS;
 
 /**
  * The dialog to create footprint position files and choose options (one or 2 files, units
@@ -36,6 +37,7 @@ class DIALOG_GEN_FOOTPRINT_POSITION : public DIALOG_GEN_FOOTPRINT_POSITION_BASE
 {
 public:
     DIALOG_GEN_FOOTPRINT_POSITION( PCB_EDIT_FRAME* aEditFrame );
+    DIALOG_GEN_FOOTPRINT_POSITION( JOB_EXPORT_PCB_POS* aJob, PCB_EDIT_FRAME* aEditFrame, wxWindow* aParent );
 
 private:
     void initDialog();
@@ -78,4 +80,5 @@ private:
 private:
     PCB_EDIT_FRAME* m_editFrame;
     REPORTER*       m_reporter;
+    JOB_EXPORT_PCB_POS* m_job;
 };
\ No newline at end of file
diff --git a/pcbnew/dialogs/dialog_gendrill.cpp b/pcbnew/dialogs/dialog_gendrill.cpp
index bbc0bdf7b7..e6eb92b0a4 100644
--- a/pcbnew/dialogs/dialog_gendrill.cpp
+++ b/pcbnew/dialogs/dialog_gendrill.cpp
@@ -45,6 +45,7 @@
 #include <wx/msgdlg.h>
 #include <wx/dirdlg.h>
 #include <wx/filedlg.h>
+#include <jobs/job_export_pcb_drill.h>
 
 // list of allowed precision for EXCELLON files, for integer format:
 // Due to difference between inches and mm,
@@ -66,7 +67,7 @@ int BOARD_EDITOR_CONTROL::GenerateDrillFiles( const TOOL_EVENT& aEvent )
 }
 
 
-DIALOG_GENDRILL::DIALOG_GENDRILL(  PCB_EDIT_FRAME* aPcbEditFrame, wxWindow* aParent  ) :
+DIALOG_GENDRILL::DIALOG_GENDRILL( PCB_EDIT_FRAME* aPcbEditFrame, wxWindow* aParent  ) :
     DIALOG_GENDRILL_BASE( aParent )
 {
     m_pcbEditFrame = aPcbEditFrame;
@@ -85,6 +86,30 @@ DIALOG_GENDRILL::DIALOG_GENDRILL(  PCB_EDIT_FRAME* aPcbEditFrame, wxWindow* aPar
 }
 
 
+
+DIALOG_GENDRILL::DIALOG_GENDRILL( PCB_EDIT_FRAME* aPcbEditFrame, JOB_EXPORT_PCB_DRILL* aJob,
+                                  wxWindow* aParent ) :
+    DIALOG_GENDRILL_BASE( aParent )
+{
+    m_pcbEditFrame = aPcbEditFrame;
+    m_board = m_pcbEditFrame->GetBoard();
+    m_job = aJob;
+
+    // hide ui elements that dont belong for job config
+    m_buttonReport->Hide();
+    bMainSizer->Remove( bMsgSizer );
+    m_messagesBox->Hide();
+
+    m_sdbSizerApply->Hide();
+    SetupStandardButtons( { { wxID_OK, _( "Save" ) }, { wxID_CANCEL, _( "Cancel" ) } } );
+    m_buttonsSizer->Layout();
+
+    SetReturnCode( 1 );
+
+    GetSizer()->SetSizeHints( this );
+}
+
+
 // Static members of DIALOG_GENDRILL
 int DIALOG_GENDRILL::m_UnitDrillIsInch  = true;     // Only for Excellon format
 int DIALOG_GENDRILL::m_ZerosFormat      = EXCELLON_WRITER::DECIMAL_FORMAT;
@@ -100,46 +125,87 @@ DIALOG_GENDRILL::~DIALOG_GENDRILL()
 }
 
 
+bool DIALOG_GENDRILL::TransferDataFromWindow()
+{
+    return true;
+}
+
+
+bool DIALOG_GENDRILL::TransferDataToWindow()
+{
+	initDialog();
+	return true;
+}
+
+
 void DIALOG_GENDRILL::initDialog()
 {
-    auto cfg = m_pcbEditFrame->GetPcbNewSettings();
+    if( !m_job )
+    {
+        auto cfg = m_pcbEditFrame->GetPcbNewSettings();
 
-    m_Merge_PTH_NPTH           = cfg->m_GenDrill.merge_pth_npth;
-    m_MinimalHeader            = cfg->m_GenDrill.minimal_header;
-    m_Mirror                   = cfg->m_GenDrill.mirror;
-    m_UnitDrillIsInch          = cfg->m_GenDrill.unit_drill_is_inch;
-    m_UseRouteModeForOvalHoles = cfg->m_GenDrill.use_route_for_oval_holes;
-    m_drillFileType            = cfg->m_GenDrill.drill_file_type;
-    m_mapFileType              = cfg->m_GenDrill.map_file_type;
-    m_ZerosFormat              = cfg->m_GenDrill.zeros_format;
+        m_Merge_PTH_NPTH = cfg->m_GenDrill.merge_pth_npth;
+        m_MinimalHeader = cfg->m_GenDrill.minimal_header;
+        m_Mirror = cfg->m_GenDrill.mirror;
+        m_UnitDrillIsInch = cfg->m_GenDrill.unit_drill_is_inch;
+        m_UseRouteModeForOvalHoles = cfg->m_GenDrill.use_route_for_oval_holes;
+        m_drillFileType = cfg->m_GenDrill.drill_file_type;
+        m_mapFileType = cfg->m_GenDrill.map_file_type;
+        m_ZerosFormat = cfg->m_GenDrill.zeros_format;
+
+        // Ensure validity of m_mapFileType
+        if( m_mapFileType < 0 || m_mapFileType >= (int) m_Choice_Drill_Map->GetCount() )
+            m_mapFileType = m_Choice_Drill_Map->GetCount() - 1; // last item in list = default = PDF
+	}
 
     m_drillOriginIsAuxAxis = m_plotOpts.GetUseAuxOrigin();
 
-    // Ensure validity of m_mapFileType
-    if( m_mapFileType < 0 || m_mapFileType >= (int)m_Choice_Drill_Map->GetCount() )
-        m_mapFileType = m_Choice_Drill_Map->GetCount() - 1;  // last item in list = default = PDF
-
     InitDisplayParams();
 }
 
 
 void DIALOG_GENDRILL::InitDisplayParams()
 {
-    m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
+    if( !m_job )
+    {
+        m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
 
-    m_rbExcellon->SetValue( m_drillFileType == 0 );
-    m_rbGerberX2->SetValue( m_drillFileType == 1 );
-    m_Choice_Unit->SetSelection( m_UnitDrillIsInch ? 1 : 0 );
-    m_Choice_Zeros_Format->SetSelection( m_ZerosFormat );
-    UpdatePrecisionOptions();
-    m_Check_Minimal->SetValue( m_MinimalHeader );
+        m_rbExcellon->SetValue( m_drillFileType == 0 );
+        m_rbGerberX2->SetValue( m_drillFileType == 1 );
+        m_Choice_Unit->SetSelection( m_UnitDrillIsInch ? 1 : 0 );
+        m_Choice_Zeros_Format->SetSelection( m_ZerosFormat );
+        UpdatePrecisionOptions();
+        m_Check_Minimal->SetValue( m_MinimalHeader );
 
-    m_Choice_Drill_Offset->SetSelection( m_drillOriginIsAuxAxis ? 1 : 0 );
+        m_Choice_Drill_Offset->SetSelection( m_drillOriginIsAuxAxis ? 1 : 0 );
 
-    m_Check_Mirror->SetValue( m_Mirror );
-    m_Check_Merge_PTH_NPTH->SetValue( m_Merge_PTH_NPTH );
-    m_Choice_Drill_Map->SetSelection( m_mapFileType );
-    m_radioBoxOvalHoleMode->SetSelection( m_UseRouteModeForOvalHoles ? 0 : 1 );
+        m_Check_Mirror->SetValue( m_Mirror );
+        m_Check_Merge_PTH_NPTH->SetValue( m_Merge_PTH_NPTH );
+        m_Choice_Drill_Map->SetSelection( m_mapFileType );
+        m_radioBoxOvalHoleMode->SetSelection( m_UseRouteModeForOvalHoles ? 0 : 1 );
+
+        // Output directory
+        m_outputDirectoryName->SetValue( m_plotOpts.GetOutputDirectory() );
+    }
+    else
+    {
+        m_browseButton->Hide();
+        m_outputDirectoryName->SetValue( m_job->GetOutputPath() );
+
+        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 );
+        m_Choice_Unit->SetSelection( m_job->m_drillUnits == JOB_EXPORT_PCB_DRILL::DRILL_UNITS::INCHES );
+        m_Choice_Zeros_Format->SetSelection( static_cast<int>( m_job->m_zeroFormat ) );
+        UpdatePrecisionOptions();
+        m_Check_Minimal->SetValue( m_job->m_excellonMinimalHeader );
+
+        m_Choice_Drill_Offset->SetSelection( m_job->m_drillOrigin == JOB_EXPORT_PCB_DRILL::DRILL_ORIGIN::PLOT );
+
+        m_Check_Mirror->SetValue( m_job->m_excellonMirrorY );
+        m_Check_Merge_PTH_NPTH->SetValue( m_job->m_excellonCombinePTHNPTH );
+        m_Choice_Drill_Map->SetSelection( static_cast<int>( m_job->m_mapFormat ) );
+        m_radioBoxOvalHoleMode->SetSelection( m_job->m_excellonOvalDrillRoute ? 0 : 1 );
+    }
 
     m_platedPadsHoleCount    = 0;
     m_notplatedPadsHoleCount = 0;
@@ -197,9 +263,6 @@ void DIALOG_GENDRILL::InitDisplayParams()
     m_MicroViasInfoMsg->SetLabel( wxString() << m_microViasCount );
     m_BuriedViasInfoMsg->SetLabel( wxString() << m_blindOrBuriedViasCount );
 
-    // Output directory
-    m_outputDirectoryName->SetValue( m_plotOpts.GetOutputDirectory() );
-
     wxCommandEvent dummy;
     onFileFormatSelection( dummy );
 }
@@ -256,13 +319,36 @@ void DIALOG_GENDRILL::OnSelDrillUnitsSelected( wxCommandEvent& event )
 
 void DIALOG_GENDRILL::OnGenMapFile( wxCommandEvent& event )
 {
-    GenDrillAndMapFiles( false, true );
+    if( !m_job )
+    {
+        GenDrillAndMapFiles( false, true );
+    }
 }
 
 
 void DIALOG_GENDRILL::OnGenDrillFile( wxCommandEvent& event )
 {
-    GenDrillAndMapFiles( true, false );
+    if( !m_job )
+    {
+        GenDrillAndMapFiles( true, false );
+    }
+    else
+    {
+        m_job->SetOutputPath( 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_Choice_Unit->GetSelection() == 0
+							? JOB_EXPORT_PCB_DRILL::DRILL_UNITS::MILLIMETERS
+							: JOB_EXPORT_PCB_DRILL::DRILL_UNITS::INCHES;
+        m_job->m_drillOrigin = static_cast<JOB_EXPORT_PCB_DRILL::DRILL_ORIGIN>( m_Choice_Drill_Offset->GetSelection() );
+        m_job->m_excellonCombinePTHNPTH = m_Check_Merge_PTH_NPTH->IsChecked();
+        m_job->m_excellonMinimalHeader = m_Check_Minimal->IsChecked();
+        m_job->m_excellonMirrorY = m_Check_Mirror->IsChecked();
+        m_job->m_excellonOvalDrillRoute = m_radioBoxOvalHoleMode->GetSelection() == 0;
+        m_job->m_mapFormat = static_cast<JOB_EXPORT_PCB_DRILL::MAP_FORMAT>( m_Choice_Drill_Map->GetSelection() );
+        m_job->m_zeroFormat = static_cast<JOB_EXPORT_PCB_DRILL::ZEROS_FORMAT>( m_Choice_Zeros_Format->GetSelection() );
+        Close();
+    }
 }
 
 
diff --git a/pcbnew/dialogs/dialog_gendrill.h b/pcbnew/dialogs/dialog_gendrill.h
index 1b6bc4643e..03c2e900d6 100644
--- a/pcbnew/dialogs/dialog_gendrill.h
+++ b/pcbnew/dialogs/dialog_gendrill.h
@@ -28,6 +28,8 @@
 #include <gendrill_file_writer_base.h>      // for DRILL_PRECISION definition
 #include <dialog_gendrill_base.h>
 
+class JOB_EXPORT_PCB_DRILL;
+
 class DIALOG_GENDRILL : public DIALOG_GENDRILL_BASE
 {
 public:
@@ -36,6 +38,7 @@ public:
      * @param aParent is the parent window caller ( the board edit frame or a dialog ).
      */
     DIALOG_GENDRILL( PCB_EDIT_FRAME* aPcbEditFrame, wxWindow* aParent );
+    DIALOG_GENDRILL( PCB_EDIT_FRAME* aPcbEditFrame, JOB_EXPORT_PCB_DRILL* aJob, wxWindow* aParent );
     ~DIALOG_GENDRILL();
 
     /**
@@ -43,6 +46,9 @@ public:
      */
     void             UpdateDrillParams();
 
+    bool TransferDataFromWindow() override;
+    bool TransferDataToWindow() override;
+
 private:
     void initDialog();
     void InitDisplayParams();
@@ -108,6 +114,8 @@ private:
     PCB_EDIT_FRAME*  m_pcbEditFrame;
     BOARD*           m_board;
     PCB_PLOT_PARAMS  m_plotOpts;
+    JOB_EXPORT_PCB_DRILL* m_job;
+
     bool             m_drillOriginIsAuxAxis;     // Axis selection (main / auxiliary)
                                                  // for drill origin coordinates
     int              m_platedPadsHoleCount;
diff --git a/pcbnew/dialogs/dialog_gendrill_base.cpp b/pcbnew/dialogs/dialog_gendrill_base.cpp
index 6a15882af1..53f1443aff 100644
--- a/pcbnew/dialogs/dialog_gendrill_base.cpp
+++ b/pcbnew/dialogs/dialog_gendrill_base.cpp
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
+// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO *NOT* EDIT THIS FILE!
@@ -15,7 +15,6 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
 {
 	this->SetSizeHints( wxDefaultSize, wxDefaultSize );
 
-	wxBoxSizer* bMainSizer;
 	bMainSizer = new wxBoxSizer( wxVERTICAL );
 
 	wxBoxSizer* bupperSizer;
@@ -200,7 +199,6 @@ DIALOG_GENDRILL_BASE::DIALOG_GENDRILL_BASE( wxWindow* parent, wxWindowID id, con
 
 	bMainSizer->Add( bmiddlerSizer, 0, wxEXPAND|wxTOP, 8 );
 
-	wxStaticBoxSizer* bMsgSizer;
 	bMsgSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Messages") ), wxVERTICAL );
 
 	m_messagesBox = new wxTextCtrl( bMsgSizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY );
diff --git a/pcbnew/dialogs/dialog_gendrill_base.fbp b/pcbnew/dialogs/dialog_gendrill_base.fbp
index d5425bdc44..d5b7582b59 100644
--- a/pcbnew/dialogs/dialog_gendrill_base.fbp
+++ b/pcbnew/dialogs/dialog_gendrill_base.fbp
@@ -1,1967 +1,1997 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <wxFormBuilder_Project>
-    <FileVersion major="1" minor="16" />
-    <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_gendrill_base</property>
-        <property name="first_id">1000</property>
-        <property name="help_provider">none</property>
-        <property name="image_path_wrapper_function_name"></property>
-        <property name="indent_with_spaces"></property>
-        <property name="internationalize">1</property>
-        <property name="name">dialog_gendrill_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_array_enum">0</property>
-        <property name="use_enum">0</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">wxBOTH</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>
+  <FileVersion major="1" minor="18"/>
+  <object class="Project" expanded="true">
+    <property name="code_generation">C++</property>
+    <property name="cpp_class_decoration"></property>
+    <property name="cpp_disconnect_events">1</property>
+    <property name="cpp_event_generation">connect</property>
+    <property name="cpp_help_provider">none</property>
+    <property name="cpp_namespace"></property>
+    <property name="cpp_precompiled_header"></property>
+    <property name="cpp_use_array_enum">0</property>
+    <property name="cpp_use_enum">0</property>
+    <property name="embedded_files_path">res</property>
+    <property name="encoding">UTF-8</property>
+    <property name="file">dialog_gendrill_base</property>
+    <property name="first_id">1000</property>
+    <property name="internationalize">1</property>
+    <property name="lua_skip_events">1</property>
+    <property name="lua_ui_table">UI</property>
+    <property name="name">dialog_gendrill_base</property>
+    <property name="path">.</property>
+    <property name="php_disconnect_events">0</property>
+    <property name="php_disconnect_mode">source_name</property>
+    <property name="php_skip_events">1</property>
+    <property name="python_disconnect_events">0</property>
+    <property name="python_disconnect_mode">source_name</property>
+    <property name="python_image_path_wrapper_function_name"></property>
+    <property name="python_indent_with_spaces"></property>
+    <property name="python_skip_events">1</property>
+    <property name="relative_path">1</property>
+    <property name="use_microsoft_bom">0</property>
+    <property name="use_native_eol">0</property>
+    <object class="Dialog" expanded="true">
+      <property name="aui_managed">0</property>
+      <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
+      <property name="bg"></property>
+      <property name="center">wxBOTH</property>
+      <property name="context_help"></property>
+      <property name="context_menu">1</property>
+      <property name="drag_accept_files">0</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"></property>
+      <property name="name">DIALOG_GENDRILL_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">Generate Drill Files</property>
+      <property name="tooltip"></property>
+      <property name="two_step_creation">0</property>
+      <property name="window_extra_style"></property>
+      <property name="window_name"></property>
+      <property name="window_style"></property>
+      <event name="OnClose">onCloseDlg</event>
+      <object class="wxBoxSizer" expanded="true">
+        <property name="minimum_size"></property>
+        <property name="name">bMainSizer</property>
+        <property name="orient">wxVERTICAL</property>
+        <property name="permission">protected</property>
+        <object class="sizeritem" expanded="true">
+          <property name="border">10</property>
+          <property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
+          <property name="proportion">0</property>
+          <object class="wxBoxSizer" expanded="true">
             <property name="minimum_size"></property>
-            <property name="name">DIALOG_GENDRILL_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">Generate Drill Files</property>
-            <property name="tooltip"></property>
-            <property name="two_step_creation">0</property>
-            <property name="window_extra_style"></property>
-            <property name="window_name"></property>
-            <property name="window_style"></property>
-            <event name="OnClose">onCloseDlg</event>
-            <object class="wxBoxSizer" expanded="1">
+            <property name="name">bupperSizer</property>
+            <property name="orient">wxHORIZONTAL</property>
+            <property name="permission">none</property>
+            <object class="sizeritem" expanded="true">
+              <property name="border">10</property>
+              <property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property>
+              <property name="proportion">0</property>
+              <object class="wxStaticText" expanded="true">
+                <property name="BottomDockable">1</property>
+                <property name="LeftDockable">1</property>
+                <property name="RightDockable">1</property>
+                <property name="TopDockable">1</property>
+                <property name="aui_layer">0</property>
+                <property name="aui_name"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</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="drag_accept_files">0</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">Output folder:</property>
+                <property name="markup">0</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="name">bMainSizer</property>
+                <property name="moveable">1</property>
+                <property name="name">staticTextOutputDir</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"></property>
+                <property name="window_extra_style"></property>
+                <property name="window_name"></property>
+                <property name="window_style"></property>
+                <property name="wrap">-1</property>
+              </object>
+            </object>
+            <object class="sizeritem" expanded="true">
+              <property name="border">0</property>
+              <property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT</property>
+              <property name="proportion">1</property>
+              <object class="wxTextCtrl" expanded="true">
+                <property name="BottomDockable">1</property>
+                <property name="LeftDockable">1</property>
+                <property name="RightDockable">1</property>
+                <property name="TopDockable">1</property>
+                <property name="aui_layer">0</property>
+                <property name="aui_name"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</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="drag_accept_files">0</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="maxlength">0</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_outputDirectoryName</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"></property>
+                <property name="toolbar_pane">0</property>
+                <property name="tooltip"></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="value"></property>
+                <property name="window_extra_style"></property>
+                <property name="window_name"></property>
+                <property name="window_style"></property>
+              </object>
+            </object>
+            <object class="sizeritem" expanded="true">
+              <property name="border">7</property>
+              <property name="flag">wxALIGN_CENTER_VERTICAL</property>
+              <property name="proportion">0</property>
+              <object class="wxBitmapButton" expanded="true">
+                <property name="BottomDockable">1</property>
+                <property name="LeftDockable">1</property>
+                <property name="RightDockable">1</property>
+                <property name="TopDockable">1</property>
+                <property name="aui_layer">0</property>
+                <property name="aui_name"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</property>
+                <property name="auth_needed">0</property>
+                <property name="best_size"></property>
+                <property name="bg"></property>
+                <property name="bitmap"></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="current"></property>
+                <property name="default">0</property>
+                <property name="default_pane">0</property>
+                <property name="disabled"></property>
+                <property name="dock">Dock</property>
+                <property name="dock_fixed">0</property>
+                <property name="docking">Left</property>
+                <property name="drag_accept_files">0</property>
+                <property name="enabled">1</property>
+                <property name="fg"></property>
+                <property name="floatable">1</property>
+                <property name="focus"></property>
+                <property name="font"></property>
+                <property name="gripper">0</property>
+                <property name="hidden">0</property>
+                <property name="id">wxID_ANY</property>
+                <property name="label">Browse</property>
+                <property name="margins"></property>
+                <property name="markup">0</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_browseButton</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="position"></property>
+                <property name="pressed"></property>
+                <property name="resize">Resizable</property>
+                <property name="show">1</property>
+                <property name="size">-1,-1</property>
+                <property name="style"></property>
+                <property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
+                <property name="toolbar_pane">0</property>
+                <property name="tooltip"></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="OnButtonClick">OnOutputDirectoryBrowseClicked</event>
+              </object>
+            </object>
+          </object>
+        </object>
+        <object class="sizeritem" expanded="true">
+          <property name="border">8</property>
+          <property name="flag">wxEXPAND|wxTOP</property>
+          <property name="proportion">0</property>
+          <object class="wxBoxSizer" expanded="false">
+            <property name="minimum_size"></property>
+            <property name="name">bmiddlerSizer</property>
+            <property name="orient">wxHORIZONTAL</property>
+            <property name="permission">none</property>
+            <object class="sizeritem" expanded="false">
+              <property name="border">5</property>
+              <property name="flag">wxEXPAND</property>
+              <property name="proportion">1</property>
+              <object class="wxBoxSizer" expanded="false">
+                <property name="minimum_size"></property>
+                <property name="name">bMiddleSizer</property>
                 <property name="orient">wxVERTICAL</property>
                 <property name="permission">none</property>
-                <object class="sizeritem" expanded="1">
-                    <property name="border">10</property>
-                    <property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
-                    <property name="proportion">0</property>
-                    <object class="wxBoxSizer" expanded="1">
-                        <property name="minimum_size"></property>
-                        <property name="name">bupperSizer</property>
-                        <property name="orient">wxHORIZONTAL</property>
-                        <property name="permission">none</property>
-                        <object class="sizeritem" expanded="1">
-                            <property name="border">10</property>
-                            <property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property>
-                            <property name="proportion">0</property>
-                            <object class="wxStaticText" 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="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">Output folder:</property>
-                                <property name="markup">0</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">staticTextOutputDir</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"></property>
-                                <property name="window_extra_style"></property>
-                                <property name="window_name"></property>
-                                <property name="window_style"></property>
-                                <property name="wrap">-1</property>
-                            </object>
-                        </object>
-                        <object class="sizeritem" expanded="1">
-                            <property name="border">0</property>
-                            <property name="flag">wxALIGN_CENTER_VERTICAL|wxLEFT</property>
-                            <property name="proportion">1</property>
-                            <object class="wxTextCtrl" 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="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="maxlength">0</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_outputDirectoryName</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"></property>
-                                <property name="toolbar_pane">0</property>
-                                <property name="tooltip"></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="value"></property>
-                                <property name="window_extra_style"></property>
-                                <property name="window_name"></property>
-                                <property name="window_style"></property>
-                            </object>
-                        </object>
-                        <object class="sizeritem" expanded="1">
-                            <property name="border">7</property>
-                            <property name="flag">wxALIGN_CENTER_VERTICAL</property>
-                            <property name="proportion">0</property>
-                            <object class="wxBitmapButton" 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="auth_needed">0</property>
-                                <property name="best_size"></property>
-                                <property name="bg"></property>
-                                <property name="bitmap"></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="current"></property>
-                                <property name="default">0</property>
-                                <property name="default_pane">0</property>
-                                <property name="disabled"></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="focus"></property>
-                                <property name="font"></property>
-                                <property name="gripper">0</property>
-                                <property name="hidden">0</property>
-                                <property name="id">wxID_ANY</property>
-                                <property name="label">Browse</property>
-                                <property name="margins"></property>
-                                <property name="markup">0</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_browseButton</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="position"></property>
-                                <property name="pressed"></property>
-                                <property name="resize">Resizable</property>
-                                <property name="show">1</property>
-                                <property name="size">-1,-1</property>
-                                <property name="style"></property>
-                                <property name="subclass">STD_BITMAP_BUTTON; widgets/std_bitmap_button.h; forward_declare</property>
-                                <property name="toolbar_pane">0</property>
-                                <property name="tooltip"></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="OnButtonClick">OnOutputDirectoryBrowseClicked</event>
-                            </object>
-                        </object>
-                    </object>
-                </object>
-                <object class="sizeritem" expanded="1">
-                    <property name="border">8</property>
-                    <property name="flag">wxEXPAND|wxTOP</property>
-                    <property name="proportion">0</property>
-                    <object class="wxBoxSizer" expanded="1">
-                        <property name="minimum_size"></property>
-                        <property name="name">bmiddlerSizer</property>
-                        <property name="orient">wxHORIZONTAL</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">bMiddleSizer</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|wxALL</property>
-                                    <property name="proportion">1</property>
-                                    <object class="wxStaticBoxSizer" expanded="1">
-                                        <property name="id">wxID_ANY</property>
-                                        <property name="label">Drill File Format</property>
-                                        <property name="minimum_size"></property>
-                                        <property name="name">sbSizer6</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">wxBOTTOM|wxRIGHT</property>
-                                            <property name="proportion">0</property>
-                                            <object class="wxRadioButton" 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="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">Excellon</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_rbExcellon</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"></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="value">0</property>
-                                                <property name="window_extra_style"></property>
-                                                <property name="window_name"></property>
-                                                <property name="window_style"></property>
-                                                <event name="OnRadioButton">onFileFormatSelection</event>
-                                            </object>
-                                        </object>
-                                        <object class="sizeritem" expanded="1">
-                                            <property name="border">12</property>
-                                            <property name="flag">wxEXPAND|wxLEFT</property>
-                                            <property name="proportion">1</property>
-                                            <object class="wxBoxSizer" expanded="1">
-                                                <property name="minimum_size"></property>
-                                                <property name="name">bSizerExcellonOptions</property>
-                                                <property name="orient">wxVERTICAL</property>
-                                                <property name="permission">none</property>
-                                                <object class="sizeritem" expanded="1">
-                                                    <property name="border">5</property>
-                                                    <property name="flag">wxLEFT</property>
-                                                    <property name="proportion">0</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">Mirror Y axis</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_Check_Mirror</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"></property>
-                                                        <property name="toolbar_pane">0</property>
-                                                        <property name="tooltip">Not recommended.&#x0A;Used mostly by users who make the boards themselves.</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>
-                                                    </object>
-                                                </object>
-                                                <object class="sizeritem" expanded="1">
-                                                    <property name="border">5</property>
-                                                    <property name="flag">wxRIGHT|wxLEFT</property>
-                                                    <property name="proportion">0</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">Minimal header</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_Check_Minimal</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"></property>
-                                                        <property name="toolbar_pane">0</property>
-                                                        <property name="tooltip">Not recommended.&#x0A;Only use it for board houses which do not accept fully featured headers.</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>
-                                                    </object>
-                                                </object>
-                                                <object class="sizeritem" expanded="1">
-                                                    <property name="border">5</property>
-                                                    <property name="flag">wxLEFT</property>
-                                                    <property name="proportion">0</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">PTH and NPTH in single file</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_Check_Merge_PTH_NPTH</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"></property>
-                                                        <property name="toolbar_pane">0</property>
-                                                        <property name="tooltip">Not recommended.&#x0A;Only use for board houses which ask for merged PTH and NPTH into a single file.</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>
-                                                    </object>
-                                                </object>
-                                                <object class="sizeritem" expanded="1">
-                                                    <property name="border">5</property>
-                                                    <property name="flag">wxALL|wxEXPAND</property>
-                                                    <property name="proportion">0</property>
-                                                    <object class="wxRadioBox" 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="choices">&quot;Use route command (recommended)&quot; &quot;Use alternate drill mode&quot;</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">Oval Holes Drill Mode</property>
-                                                        <property name="majorDimension">1</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_radioBoxOvalHoleMode</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="selection">0</property>
-                                                        <property name="show">1</property>
-                                                        <property name="size"></property>
-                                                        <property name="style">wxRA_SPECIFY_COLS</property>
-                                                        <property name="subclass">; ; forward_declare</property>
-                                                        <property name="toolbar_pane">0</property>
-                                                        <property name="tooltip">Oval holes frequently create problems for board houses.&#x0A;&quot;Use route command&quot; uses the usual G00 route command (recommended)&#x0A; &quot;Use alternate mode&quot; uses another drill/ route command (G85)&#x0A;(Use it only if the recommended command does not work)</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>
-                                                    </object>
-                                                </object>
-                                            </object>
-                                        </object>
-                                        <object class="sizeritem" expanded="1">
-                                            <property name="border">5</property>
-                                            <property name="flag">wxTOP|wxBOTTOM|wxRIGHT</property>
-                                            <property name="proportion">0</property>
-                                            <object class="wxRadioButton" 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="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">Gerber X2</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_rbGerberX2</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"></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="value">0</property>
-                                                <property name="window_extra_style"></property>
-                                                <property name="window_name"></property>
-                                                <property name="window_style"></property>
-                                                <event name="OnRadioButton">onFileFormatSelection</event>
-                                            </object>
-                                        </object>
-                                    </object>
-                                </object>
-                                <object class="sizeritem" expanded="1">
-                                    <property name="border">5</property>
-                                    <property name="flag">wxALL|wxEXPAND</property>
-                                    <property name="proportion">0</property>
-                                    <object class="wxRadioBox" 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="choices">&quot;PostScript&quot; &quot;Gerber X2&quot; &quot;DXF&quot; &quot;SVG&quot; &quot;PDF&quot;</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">Map File Format</property>
-                                        <property name="majorDimension">1</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_Choice_Drill_Map</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="selection">4</property>
-                                        <property name="show">1</property>
-                                        <property name="size"></property>
-                                        <property name="style">wxRA_SPECIFY_COLS</property>
-                                        <property name="subclass"></property>
-                                        <property name="toolbar_pane">0</property>
-                                        <property name="tooltip">Creates a drill map in PDF or other formats</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>
-                                    </object>
-                                </object>
-                            </object>
-                        </object>
-                        <object class="sizeritem" expanded="1">
-                            <property name="border">5</property>
-                            <property name="flag">wxEXPAND</property>
-                            <property name="proportion">0</property>
-                            <object class="wxBoxSizer" expanded="1">
-                                <property name="minimum_size"></property>
-                                <property name="name">bLeftSizer</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="wxRadioBox" 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="choices">&quot;Absolute&quot; &quot;Drill/place file origin&quot;</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">Drill Origin</property>
-                                        <property name="majorDimension">1</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_Choice_Drill_Offset</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="selection">0</property>
-                                        <property name="show">1</property>
-                                        <property name="size"></property>
-                                        <property name="style">wxRA_SPECIFY_COLS</property>
-                                        <property name="subclass"></property>
-                                        <property name="toolbar_pane">0</property>
-                                        <property name="tooltip">Choose the coordinate origin: absolute or relative to the drill/place file origin</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>
-                                    </object>
-                                </object>
-                                <object class="sizeritem" expanded="1">
-                                    <property name="border">5</property>
-                                    <property name="flag">wxALL|wxEXPAND</property>
-                                    <property name="proportion">0</property>
-                                    <object class="wxRadioBox" 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="choices">&quot;Millimeters&quot; &quot;Inches&quot;</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">Drill Units</property>
-                                        <property name="majorDimension">1</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_Choice_Unit</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="selection">0</property>
-                                        <property name="show">1</property>
-                                        <property name="size"></property>
-                                        <property name="style">wxRA_SPECIFY_COLS</property>
-                                        <property name="subclass"></property>
-                                        <property name="toolbar_pane">0</property>
-                                        <property name="tooltip"></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="OnRadioBox">OnSelDrillUnitsSelected</event>
-                                    </object>
-                                </object>
-                                <object class="sizeritem" expanded="1">
-                                    <property name="border">5</property>
-                                    <property name="flag">wxALL|wxEXPAND</property>
-                                    <property name="proportion">0</property>
-                                    <object class="wxRadioBox" 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="choices">&quot;Decimal format (recommended)&quot; &quot;Suppress leading zeros&quot; &quot;Suppress trailing zeros&quot; &quot;Keep zeros&quot;</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">Zeros Format</property>
-                                        <property name="majorDimension">1</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_Choice_Zeros_Format</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="selection">0</property>
-                                        <property name="show">1</property>
-                                        <property name="size"></property>
-                                        <property name="style">wxRA_SPECIFY_COLS</property>
-                                        <property name="subclass"></property>
-                                        <property name="toolbar_pane">0</property>
-                                        <property name="tooltip">Choose EXCELLON numbers notation</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="OnRadioBox">OnSelZerosFmtSelected</event>
-                                    </object>
-                                </object>
-                                <object class="sizeritem" expanded="1">
-                                    <property name="border">5</property>
-                                    <property name="flag">wxEXPAND</property>
-                                    <property name="proportion">0</property>
-                                    <object class="wxFlexGridSizer" expanded="1">
-                                        <property name="cols">2</property>
-                                        <property name="flexible_direction">wxBOTH</property>
-                                        <property name="growablecols">1</property>
-                                        <property name="growablerows"></property>
-                                        <property name="hgap">0</property>
-                                        <property name="minimum_size"></property>
-                                        <property name="name">fgSizer1</property>
-                                        <property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
-                                        <property name="permission">none</property>
-                                        <property name="rows">0</property>
-                                        <property name="vgap">0</property>
-                                        <object class="sizeritem" expanded="1">
-                                            <property name="border">10</property>
-                                            <property name="flag">wxALL</property>
-                                            <property name="proportion">0</property>
-                                            <object class="wxStaticText" 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="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">Precision:</property>
-                                                <property name="markup">0</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_staticTextTitle</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"></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"></property>
-                                                <property name="wrap">-1</property>
-                                            </object>
-                                        </object>
-                                        <object class="sizeritem" expanded="1">
-                                            <property name="border">10</property>
-                                            <property name="flag">wxALL</property>
-                                            <property name="proportion">0</property>
-                                            <object class="wxStaticText" 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="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">Precision</property>
-                                                <property name="markup">0</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_staticTextPrecision</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"></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"></property>
-                                                <property name="wrap">-1</property>
-                                            </object>
-                                        </object>
-                                    </object>
-                                </object>
-                            </object>
-                        </object>
-                        <object class="sizeritem" expanded="1">
-                            <property name="border">5</property>
-                            <property name="flag">wxEXPAND|wxTOP</property>
-                            <property name="proportion">0</property>
-                            <object class="wxBoxSizer" expanded="0">
-                                <property name="minimum_size"></property>
-                                <property name="name">bRightBoxSizer</property>
-                                <property name="orient">wxVERTICAL</property>
-                                <property name="permission">none</property>
-                                <object class="sizeritem" expanded="0">
-                                    <property name="border">5</property>
-                                    <property name="flag">wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT</property>
-                                    <property name="proportion">1</property>
-                                    <object class="wxStaticBoxSizer" expanded="0">
-                                        <property name="id">wxID_ANY</property>
-                                        <property name="label">Hole Counts</property>
-                                        <property name="minimum_size"></property>
-                                        <property name="name">sbSizerHoles</property>
-                                        <property name="orient">wxVERTICAL</property>
-                                        <property name="parent">1</property>
-                                        <property name="permission">none</property>
-                                        <object class="sizeritem" expanded="0">
-                                            <property name="border">5</property>
-                                            <property name="flag">wxEXPAND</property>
-                                            <property name="proportion">1</property>
-                                            <object class="wxFlexGridSizer" expanded="0">
-                                                <property name="cols">2</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">fgSizer2</property>
-                                                <property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
-                                                <property name="permission">none</property>
-                                                <property name="rows">0</property>
-                                                <property name="vgap">0</property>
-                                                <object class="sizeritem" expanded="0">
-                                                    <property name="border">5</property>
-                                                    <property name="flag">wxLEFT|wxRIGHT</property>
-                                                    <property name="proportion">0</property>
-                                                    <object class="wxStaticText" 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="label">Plated pads:</property>
-                                                        <property name="markup">0</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">staticTextPlatedPads</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"></property>
-                                                        <property name="window_extra_style"></property>
-                                                        <property name="window_name"></property>
-                                                        <property name="window_style"></property>
-                                                        <property name="wrap">-1</property>
-                                                    </object>
-                                                </object>
-                                                <object class="sizeritem" expanded="0">
-                                                    <property name="border">5</property>
-                                                    <property name="flag">wxALIGN_RIGHT|wxLEFT|wxRIGHT</property>
-                                                    <property name="proportion">0</property>
-                                                    <object class="wxStaticText" 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="label">0</property>
-                                                        <property name="markup">0</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_PlatedPadsCountInfoMsg</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"></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"></property>
-                                                        <property name="wrap">-1</property>
-                                                    </object>
-                                                </object>
-                                                <object class="sizeritem" expanded="0">
-                                                    <property name="border">5</property>
-                                                    <property name="flag">wxLEFT|wxRIGHT|wxTOP</property>
-                                                    <property name="proportion">0</property>
-                                                    <object class="wxStaticText" 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="label">Non-plated pads:</property>
-                                                        <property name="markup">0</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">staticTextNonPlatedPads</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"></property>
-                                                        <property name="window_extra_style"></property>
-                                                        <property name="window_name"></property>
-                                                        <property name="window_style"></property>
-                                                        <property name="wrap">-1</property>
-                                                    </object>
-                                                </object>
-                                                <object class="sizeritem" expanded="0">
-                                                    <property name="border">5</property>
-                                                    <property name="flag">wxALIGN_RIGHT|wxLEFT|wxRIGHT|wxTOP</property>
-                                                    <property name="proportion">0</property>
-                                                    <object class="wxStaticText" 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="label">0</property>
-                                                        <property name="markup">0</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_NotPlatedPadsCountInfoMsg</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"></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"></property>
-                                                        <property name="wrap">-1</property>
-                                                    </object>
-                                                </object>
-                                                <object class="sizeritem" expanded="0">
-                                                    <property name="border">4</property>
-                                                    <property name="flag">wxLEFT|wxRIGHT|wxTOP|wxALIGN_BOTTOM</property>
-                                                    <property name="proportion">0</property>
-                                                    <object class="wxStaticText" 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="label">Through vias:</property>
-                                                        <property name="markup">0</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">staticTextThroughVias</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"></property>
-                                                        <property name="window_extra_style"></property>
-                                                        <property name="window_name"></property>
-                                                        <property name="window_style"></property>
-                                                        <property name="wrap">-1</property>
-                                                    </object>
-                                                </object>
-                                                <object class="sizeritem" expanded="0">
-                                                    <property name="border">5</property>
-                                                    <property name="flag">wxALIGN_RIGHT|wxLEFT|wxRIGHT|wxTOP</property>
-                                                    <property name="proportion">0</property>
-                                                    <object class="wxStaticText" 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="label">0</property>
-                                                        <property name="markup">0</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_ThroughViasInfoMsg</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"></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"></property>
-                                                        <property name="wrap">-1</property>
-                                                    </object>
-                                                </object>
-                                                <object class="sizeritem" expanded="0">
-                                                    <property name="border">5</property>
-                                                    <property name="flag">wxLEFT|wxRIGHT|wxTOP</property>
-                                                    <property name="proportion">0</property>
-                                                    <object class="wxStaticText" 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="label">Micro vias:</property>
-                                                        <property name="markup">0</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">staticTextMicroVias</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"></property>
-                                                        <property name="window_extra_style"></property>
-                                                        <property name="window_name"></property>
-                                                        <property name="window_style"></property>
-                                                        <property name="wrap">-1</property>
-                                                    </object>
-                                                </object>
-                                                <object class="sizeritem" expanded="0">
-                                                    <property name="border">5</property>
-                                                    <property name="flag">wxALIGN_RIGHT|wxLEFT|wxRIGHT|wxTOP</property>
-                                                    <property name="proportion">0</property>
-                                                    <object class="wxStaticText" 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="label">0</property>
-                                                        <property name="markup">0</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_MicroViasInfoMsg</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"></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"></property>
-                                                        <property name="wrap">-1</property>
-                                                    </object>
-                                                </object>
-                                                <object class="sizeritem" expanded="0">
-                                                    <property name="border">5</property>
-                                                    <property name="flag">wxALL</property>
-                                                    <property name="proportion">0</property>
-                                                    <object class="wxStaticText" 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="label">Buried vias:</property>
-                                                        <property name="markup">0</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">staticTextBuriedVias</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"></property>
-                                                        <property name="window_extra_style"></property>
-                                                        <property name="window_name"></property>
-                                                        <property name="window_style"></property>
-                                                        <property name="wrap">-1</property>
-                                                    </object>
-                                                </object>
-                                                <object class="sizeritem" expanded="0">
-                                                    <property name="border">5</property>
-                                                    <property name="flag">wxALIGN_RIGHT|wxALL</property>
-                                                    <property name="proportion">0</property>
-                                                    <object class="wxStaticText" 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="label">0</property>
-                                                        <property name="markup">0</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_BuriedViasInfoMsg</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"></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"></property>
-                                                        <property name="wrap">-1</property>
-                                                    </object>
-                                                </object>
-                                            </object>
-                                        </object>
-                                    </object>
-                                </object>
-                            </object>
-                        </object>
-                    </object>
-                </object>
-                <object class="sizeritem" expanded="1">
-                    <property name="border">5</property>
-                    <property name="flag">wxALL|wxEXPAND</property>
-                    <property name="proportion">1</property>
-                    <object class="wxStaticBoxSizer" expanded="1">
+                <object class="sizeritem" expanded="false">
+                  <property name="border">5</property>
+                  <property name="flag">wxEXPAND|wxALL</property>
+                  <property name="proportion">1</property>
+                  <object class="wxStaticBoxSizer" expanded="false">
+                    <property name="id">wxID_ANY</property>
+                    <property name="label">Drill File Format</property>
+                    <property name="minimum_size"></property>
+                    <property name="name">sbSizer6</property>
+                    <property name="orient">wxVERTICAL</property>
+                    <property name="parent">1</property>
+                    <property name="permission">none</property>
+                    <object class="sizeritem" expanded="false">
+                      <property name="border">5</property>
+                      <property name="flag">wxBOTTOM|wxRIGHT</property>
+                      <property name="proportion">0</property>
+                      <object class="wxRadioButton" expanded="false">
+                        <property name="BottomDockable">1</property>
+                        <property name="LeftDockable">1</property>
+                        <property name="RightDockable">1</property>
+                        <property name="TopDockable">1</property>
+                        <property name="aui_layer">0</property>
+                        <property name="aui_name"></property>
+                        <property name="aui_position">0</property>
+                        <property name="aui_row">0</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="drag_accept_files">0</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">Messages</property>
+                        <property name="label">Excellon</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="name">bMsgSizer</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">wxALL|wxEXPAND</property>
-                            <property name="proportion">1</property>
-                            <object class="wxTextCtrl" 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="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="maxlength">0</property>
-                                <property name="min_size"></property>
-                                <property name="minimize_button">0</property>
-                                <property name="minimum_size">-1,90</property>
-                                <property name="moveable">1</property>
-                                <property name="name">m_messagesBox</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">wxTE_MULTILINE|wxTE_READONLY</property>
-                                <property name="subclass"></property>
-                                <property name="toolbar_pane">0</property>
-                                <property name="tooltip"></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="value"></property>
-                                <property name="window_extra_style"></property>
-                                <property name="window_name"></property>
-                                <property name="window_style"></property>
-                            </object>
-                        </object>
-                    </object>
-                </object>
-                <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">m_buttonsSizer</property>
-                        <property name="orient">wxHORIZONTAL</property>
+                        <property name="moveable">1</property>
+                        <property name="name">m_rbExcellon</property>
+                        <property name="pane_border">1</property>
+                        <property name="pane_position"></property>
+                        <property name="pane_size"></property>
                         <property name="permission">protected</property>
-                        <object class="sizeritem" expanded="1">
-                            <property name="border">10</property>
-                            <property name="flag">wxEXPAND|wxRIGHT|wxLEFT</property>
-                            <property name="proportion">0</property>
-                            <object class="wxButton" 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="auth_needed">0</property>
-                                <property name="best_size"></property>
-                                <property name="bg"></property>
-                                <property name="bitmap"></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="current"></property>
-                                <property name="default">0</property>
-                                <property name="default_pane">0</property>
-                                <property name="disabled"></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="focus"></property>
-                                <property name="font"></property>
-                                <property name="gripper">0</property>
-                                <property name="hidden">0</property>
-                                <property name="id">wxID_ANY</property>
-                                <property name="label">Generate Report File...</property>
-                                <property name="margins"></property>
-                                <property name="markup">0</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_buttonReport</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="position"></property>
-                                <property name="pressed"></property>
-                                <property name="resize">Resizable</property>
-                                <property name="show">1</property>
-                                <property name="size"></property>
-                                <property name="style"></property>
-                                <property name="subclass"></property>
-                                <property name="toolbar_pane">0</property>
-                                <property name="tooltip"></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="OnButtonClick">OnGenReportFile</event>
-                            </object>
-                        </object>
-                        <object class="sizeritem" expanded="1">
-                            <property name="border">5</property>
-                            <property name="flag">wxEXPAND</property>
-                            <property name="proportion">1</property>
-                            <object class="wxStdDialogButtonSizer" expanded="1">
-                                <property name="Apply">1</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_sdbSizer</property>
-                                <property name="permission">protected</property>
-                                <event name="OnApplyButtonClick">OnGenMapFile</event>
-                                <event name="OnCancelButtonClick">onQuitDlg</event>
-                                <event name="OnOKButtonClick">OnGenDrillFile</event>
-                            </object>
-                        </object>
+                        <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"></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="value">0</property>
+                        <property name="window_extra_style"></property>
+                        <property name="window_name"></property>
+                        <property name="window_style"></property>
+                        <event name="OnRadioButton">onFileFormatSelection</event>
+                      </object>
                     </object>
+                    <object class="sizeritem" expanded="false">
+                      <property name="border">12</property>
+                      <property name="flag">wxEXPAND|wxLEFT</property>
+                      <property name="proportion">1</property>
+                      <object class="wxBoxSizer" expanded="false">
+                        <property name="minimum_size"></property>
+                        <property name="name">bSizerExcellonOptions</property>
+                        <property name="orient">wxVERTICAL</property>
+                        <property name="permission">none</property>
+                        <object class="sizeritem" expanded="false">
+                          <property name="border">5</property>
+                          <property name="flag">wxLEFT</property>
+                          <property name="proportion">0</property>
+                          <object class="wxCheckBox" expanded="false">
+                            <property name="BottomDockable">1</property>
+                            <property name="LeftDockable">1</property>
+                            <property name="RightDockable">1</property>
+                            <property name="TopDockable">1</property>
+                            <property name="aui_layer">0</property>
+                            <property name="aui_name"></property>
+                            <property name="aui_position">0</property>
+                            <property name="aui_row">0</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="drag_accept_files">0</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">Mirror Y axis</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_Check_Mirror</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"></property>
+                            <property name="toolbar_pane">0</property>
+                            <property name="tooltip">Not recommended.&#x0A;Used mostly by users who make the boards themselves.</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>
+                          </object>
+                        </object>
+                        <object class="sizeritem" expanded="false">
+                          <property name="border">5</property>
+                          <property name="flag">wxRIGHT|wxLEFT</property>
+                          <property name="proportion">0</property>
+                          <object class="wxCheckBox" expanded="false">
+                            <property name="BottomDockable">1</property>
+                            <property name="LeftDockable">1</property>
+                            <property name="RightDockable">1</property>
+                            <property name="TopDockable">1</property>
+                            <property name="aui_layer">0</property>
+                            <property name="aui_name"></property>
+                            <property name="aui_position">0</property>
+                            <property name="aui_row">0</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="drag_accept_files">0</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">Minimal header</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_Check_Minimal</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"></property>
+                            <property name="toolbar_pane">0</property>
+                            <property name="tooltip">Not recommended.&#x0A;Only use it for board houses which do not accept fully featured headers.</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>
+                          </object>
+                        </object>
+                        <object class="sizeritem" expanded="false">
+                          <property name="border">5</property>
+                          <property name="flag">wxLEFT</property>
+                          <property name="proportion">0</property>
+                          <object class="wxCheckBox" expanded="false">
+                            <property name="BottomDockable">1</property>
+                            <property name="LeftDockable">1</property>
+                            <property name="RightDockable">1</property>
+                            <property name="TopDockable">1</property>
+                            <property name="aui_layer">0</property>
+                            <property name="aui_name"></property>
+                            <property name="aui_position">0</property>
+                            <property name="aui_row">0</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="drag_accept_files">0</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">PTH and NPTH in single file</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_Check_Merge_PTH_NPTH</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"></property>
+                            <property name="toolbar_pane">0</property>
+                            <property name="tooltip">Not recommended.&#x0A;Only use for board houses which ask for merged PTH and NPTH into a single file.</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>
+                          </object>
+                        </object>
+                        <object class="sizeritem" expanded="false">
+                          <property name="border">5</property>
+                          <property name="flag">wxALL|wxEXPAND</property>
+                          <property name="proportion">0</property>
+                          <object class="wxRadioBox" expanded="false">
+                            <property name="BottomDockable">1</property>
+                            <property name="LeftDockable">1</property>
+                            <property name="RightDockable">1</property>
+                            <property name="TopDockable">1</property>
+                            <property name="aui_layer">0</property>
+                            <property name="aui_name"></property>
+                            <property name="aui_position">0</property>
+                            <property name="aui_row">0</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="choices">&quot;Use route command (recommended)&quot; &quot;Use alternate drill mode&quot;</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="drag_accept_files">0</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">Oval Holes Drill Mode</property>
+                            <property name="majorDimension">1</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_radioBoxOvalHoleMode</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="selection">0</property>
+                            <property name="show">1</property>
+                            <property name="size"></property>
+                            <property name="style">wxRA_SPECIFY_COLS</property>
+                            <property name="subclass">; ; forward_declare</property>
+                            <property name="toolbar_pane">0</property>
+                            <property name="tooltip">Oval holes frequently create problems for board houses.&#x0A;&quot;Use route command&quot; uses the usual G00 route command (recommended)&#x0A; &quot;Use alternate mode&quot; uses another drill/ route command (G85)&#x0A;(Use it only if the recommended command does not work)</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>
+                          </object>
+                        </object>
+                      </object>
+                    </object>
+                    <object class="sizeritem" expanded="false">
+                      <property name="border">5</property>
+                      <property name="flag">wxTOP|wxBOTTOM|wxRIGHT</property>
+                      <property name="proportion">0</property>
+                      <object class="wxRadioButton" expanded="false">
+                        <property name="BottomDockable">1</property>
+                        <property name="LeftDockable">1</property>
+                        <property name="RightDockable">1</property>
+                        <property name="TopDockable">1</property>
+                        <property name="aui_layer">0</property>
+                        <property name="aui_name"></property>
+                        <property name="aui_position">0</property>
+                        <property name="aui_row">0</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="drag_accept_files">0</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">Gerber X2</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_rbGerberX2</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"></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="value">0</property>
+                        <property name="window_extra_style"></property>
+                        <property name="window_name"></property>
+                        <property name="window_style"></property>
+                        <event name="OnRadioButton">onFileFormatSelection</event>
+                      </object>
+                    </object>
+                  </object>
                 </object>
+                <object class="sizeritem" expanded="false">
+                  <property name="border">5</property>
+                  <property name="flag">wxALL|wxEXPAND</property>
+                  <property name="proportion">0</property>
+                  <object class="wxRadioBox" expanded="false">
+                    <property name="BottomDockable">1</property>
+                    <property name="LeftDockable">1</property>
+                    <property name="RightDockable">1</property>
+                    <property name="TopDockable">1</property>
+                    <property name="aui_layer">0</property>
+                    <property name="aui_name"></property>
+                    <property name="aui_position">0</property>
+                    <property name="aui_row">0</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="choices">&quot;PostScript&quot; &quot;Gerber X2&quot; &quot;DXF&quot; &quot;SVG&quot; &quot;PDF&quot;</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="drag_accept_files">0</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">Map File Format</property>
+                    <property name="majorDimension">1</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_Choice_Drill_Map</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="selection">4</property>
+                    <property name="show">1</property>
+                    <property name="size"></property>
+                    <property name="style">wxRA_SPECIFY_COLS</property>
+                    <property name="subclass"></property>
+                    <property name="toolbar_pane">0</property>
+                    <property name="tooltip">Creates a drill map in PDF or other formats</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>
+                  </object>
+                </object>
+              </object>
             </object>
+            <object class="sizeritem" expanded="false">
+              <property name="border">5</property>
+              <property name="flag">wxEXPAND</property>
+              <property name="proportion">0</property>
+              <object class="wxBoxSizer" expanded="false">
+                <property name="minimum_size"></property>
+                <property name="name">bLeftSizer</property>
+                <property name="orient">wxVERTICAL</property>
+                <property name="permission">none</property>
+                <object class="sizeritem" expanded="false">
+                  <property name="border">5</property>
+                  <property name="flag">wxALL|wxEXPAND</property>
+                  <property name="proportion">0</property>
+                  <object class="wxRadioBox" expanded="false">
+                    <property name="BottomDockable">1</property>
+                    <property name="LeftDockable">1</property>
+                    <property name="RightDockable">1</property>
+                    <property name="TopDockable">1</property>
+                    <property name="aui_layer">0</property>
+                    <property name="aui_name"></property>
+                    <property name="aui_position">0</property>
+                    <property name="aui_row">0</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="choices">&quot;Absolute&quot; &quot;Drill/place file origin&quot;</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="drag_accept_files">0</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">Drill Origin</property>
+                    <property name="majorDimension">1</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_Choice_Drill_Offset</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="selection">0</property>
+                    <property name="show">1</property>
+                    <property name="size"></property>
+                    <property name="style">wxRA_SPECIFY_COLS</property>
+                    <property name="subclass"></property>
+                    <property name="toolbar_pane">0</property>
+                    <property name="tooltip">Choose the coordinate origin: absolute or relative to the drill/place file origin</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>
+                  </object>
+                </object>
+                <object class="sizeritem" expanded="false">
+                  <property name="border">5</property>
+                  <property name="flag">wxALL|wxEXPAND</property>
+                  <property name="proportion">0</property>
+                  <object class="wxRadioBox" expanded="false">
+                    <property name="BottomDockable">1</property>
+                    <property name="LeftDockable">1</property>
+                    <property name="RightDockable">1</property>
+                    <property name="TopDockable">1</property>
+                    <property name="aui_layer">0</property>
+                    <property name="aui_name"></property>
+                    <property name="aui_position">0</property>
+                    <property name="aui_row">0</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="choices">&quot;Millimeters&quot; &quot;Inches&quot;</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="drag_accept_files">0</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">Drill Units</property>
+                    <property name="majorDimension">1</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_Choice_Unit</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="selection">0</property>
+                    <property name="show">1</property>
+                    <property name="size"></property>
+                    <property name="style">wxRA_SPECIFY_COLS</property>
+                    <property name="subclass"></property>
+                    <property name="toolbar_pane">0</property>
+                    <property name="tooltip"></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="OnRadioBox">OnSelDrillUnitsSelected</event>
+                  </object>
+                </object>
+                <object class="sizeritem" expanded="false">
+                  <property name="border">5</property>
+                  <property name="flag">wxALL|wxEXPAND</property>
+                  <property name="proportion">0</property>
+                  <object class="wxRadioBox" expanded="false">
+                    <property name="BottomDockable">1</property>
+                    <property name="LeftDockable">1</property>
+                    <property name="RightDockable">1</property>
+                    <property name="TopDockable">1</property>
+                    <property name="aui_layer">0</property>
+                    <property name="aui_name"></property>
+                    <property name="aui_position">0</property>
+                    <property name="aui_row">0</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="choices">&quot;Decimal format (recommended)&quot; &quot;Suppress leading zeros&quot; &quot;Suppress trailing zeros&quot; &quot;Keep zeros&quot;</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="drag_accept_files">0</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">Zeros Format</property>
+                    <property name="majorDimension">1</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_Choice_Zeros_Format</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="selection">0</property>
+                    <property name="show">1</property>
+                    <property name="size"></property>
+                    <property name="style">wxRA_SPECIFY_COLS</property>
+                    <property name="subclass"></property>
+                    <property name="toolbar_pane">0</property>
+                    <property name="tooltip">Choose EXCELLON numbers notation</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="OnRadioBox">OnSelZerosFmtSelected</event>
+                  </object>
+                </object>
+                <object class="sizeritem" expanded="false">
+                  <property name="border">5</property>
+                  <property name="flag">wxEXPAND</property>
+                  <property name="proportion">0</property>
+                  <object class="wxFlexGridSizer" expanded="false">
+                    <property name="cols">2</property>
+                    <property name="flexible_direction">wxBOTH</property>
+                    <property name="growablecols">1</property>
+                    <property name="growablerows"></property>
+                    <property name="hgap">0</property>
+                    <property name="minimum_size"></property>
+                    <property name="name">fgSizer1</property>
+                    <property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
+                    <property name="permission">none</property>
+                    <property name="rows">0</property>
+                    <property name="vgap">0</property>
+                    <object class="sizeritem" expanded="false">
+                      <property name="border">10</property>
+                      <property name="flag">wxALL</property>
+                      <property name="proportion">0</property>
+                      <object class="wxStaticText" expanded="false">
+                        <property name="BottomDockable">1</property>
+                        <property name="LeftDockable">1</property>
+                        <property name="RightDockable">1</property>
+                        <property name="TopDockable">1</property>
+                        <property name="aui_layer">0</property>
+                        <property name="aui_name"></property>
+                        <property name="aui_position">0</property>
+                        <property name="aui_row">0</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="drag_accept_files">0</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">Precision:</property>
+                        <property name="markup">0</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_staticTextTitle</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"></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"></property>
+                        <property name="wrap">-1</property>
+                      </object>
+                    </object>
+                    <object class="sizeritem" expanded="false">
+                      <property name="border">10</property>
+                      <property name="flag">wxALL</property>
+                      <property name="proportion">0</property>
+                      <object class="wxStaticText" expanded="false">
+                        <property name="BottomDockable">1</property>
+                        <property name="LeftDockable">1</property>
+                        <property name="RightDockable">1</property>
+                        <property name="TopDockable">1</property>
+                        <property name="aui_layer">0</property>
+                        <property name="aui_name"></property>
+                        <property name="aui_position">0</property>
+                        <property name="aui_row">0</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="drag_accept_files">0</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">Precision</property>
+                        <property name="markup">0</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_staticTextPrecision</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"></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"></property>
+                        <property name="wrap">-1</property>
+                      </object>
+                    </object>
+                  </object>
+                </object>
+              </object>
+            </object>
+            <object class="sizeritem" expanded="false">
+              <property name="border">5</property>
+              <property name="flag">wxEXPAND|wxTOP</property>
+              <property name="proportion">0</property>
+              <object class="wxBoxSizer" expanded="false">
+                <property name="minimum_size"></property>
+                <property name="name">bRightBoxSizer</property>
+                <property name="orient">wxVERTICAL</property>
+                <property name="permission">none</property>
+                <object class="sizeritem" expanded="false">
+                  <property name="border">5</property>
+                  <property name="flag">wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT</property>
+                  <property name="proportion">1</property>
+                  <object class="wxStaticBoxSizer" expanded="false">
+                    <property name="id">wxID_ANY</property>
+                    <property name="label">Hole Counts</property>
+                    <property name="minimum_size"></property>
+                    <property name="name">sbSizerHoles</property>
+                    <property name="orient">wxVERTICAL</property>
+                    <property name="parent">1</property>
+                    <property name="permission">none</property>
+                    <object class="sizeritem" expanded="false">
+                      <property name="border">5</property>
+                      <property name="flag">wxEXPAND</property>
+                      <property name="proportion">1</property>
+                      <object class="wxFlexGridSizer" expanded="false">
+                        <property name="cols">2</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">fgSizer2</property>
+                        <property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
+                        <property name="permission">none</property>
+                        <property name="rows">0</property>
+                        <property name="vgap">0</property>
+                        <object class="sizeritem" expanded="false">
+                          <property name="border">5</property>
+                          <property name="flag">wxLEFT|wxRIGHT</property>
+                          <property name="proportion">0</property>
+                          <object class="wxStaticText" expanded="false">
+                            <property name="BottomDockable">1</property>
+                            <property name="LeftDockable">1</property>
+                            <property name="RightDockable">1</property>
+                            <property name="TopDockable">1</property>
+                            <property name="aui_layer">0</property>
+                            <property name="aui_name"></property>
+                            <property name="aui_position">0</property>
+                            <property name="aui_row">0</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="drag_accept_files">0</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">Plated pads:</property>
+                            <property name="markup">0</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">staticTextPlatedPads</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"></property>
+                            <property name="window_extra_style"></property>
+                            <property name="window_name"></property>
+                            <property name="window_style"></property>
+                            <property name="wrap">-1</property>
+                          </object>
+                        </object>
+                        <object class="sizeritem" expanded="false">
+                          <property name="border">5</property>
+                          <property name="flag">wxALIGN_RIGHT|wxLEFT|wxRIGHT</property>
+                          <property name="proportion">0</property>
+                          <object class="wxStaticText" expanded="false">
+                            <property name="BottomDockable">1</property>
+                            <property name="LeftDockable">1</property>
+                            <property name="RightDockable">1</property>
+                            <property name="TopDockable">1</property>
+                            <property name="aui_layer">0</property>
+                            <property name="aui_name"></property>
+                            <property name="aui_position">0</property>
+                            <property name="aui_row">0</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="drag_accept_files">0</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">0</property>
+                            <property name="markup">0</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_PlatedPadsCountInfoMsg</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"></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"></property>
+                            <property name="wrap">-1</property>
+                          </object>
+                        </object>
+                        <object class="sizeritem" expanded="false">
+                          <property name="border">5</property>
+                          <property name="flag">wxLEFT|wxRIGHT|wxTOP</property>
+                          <property name="proportion">0</property>
+                          <object class="wxStaticText" expanded="false">
+                            <property name="BottomDockable">1</property>
+                            <property name="LeftDockable">1</property>
+                            <property name="RightDockable">1</property>
+                            <property name="TopDockable">1</property>
+                            <property name="aui_layer">0</property>
+                            <property name="aui_name"></property>
+                            <property name="aui_position">0</property>
+                            <property name="aui_row">0</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="drag_accept_files">0</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">Non-plated pads:</property>
+                            <property name="markup">0</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">staticTextNonPlatedPads</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"></property>
+                            <property name="window_extra_style"></property>
+                            <property name="window_name"></property>
+                            <property name="window_style"></property>
+                            <property name="wrap">-1</property>
+                          </object>
+                        </object>
+                        <object class="sizeritem" expanded="false">
+                          <property name="border">5</property>
+                          <property name="flag">wxALIGN_RIGHT|wxLEFT|wxRIGHT|wxTOP</property>
+                          <property name="proportion">0</property>
+                          <object class="wxStaticText" expanded="false">
+                            <property name="BottomDockable">1</property>
+                            <property name="LeftDockable">1</property>
+                            <property name="RightDockable">1</property>
+                            <property name="TopDockable">1</property>
+                            <property name="aui_layer">0</property>
+                            <property name="aui_name"></property>
+                            <property name="aui_position">0</property>
+                            <property name="aui_row">0</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="drag_accept_files">0</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">0</property>
+                            <property name="markup">0</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_NotPlatedPadsCountInfoMsg</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"></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"></property>
+                            <property name="wrap">-1</property>
+                          </object>
+                        </object>
+                        <object class="sizeritem" expanded="false">
+                          <property name="border">4</property>
+                          <property name="flag">wxLEFT|wxRIGHT|wxTOP|wxALIGN_BOTTOM</property>
+                          <property name="proportion">0</property>
+                          <object class="wxStaticText" expanded="false">
+                            <property name="BottomDockable">1</property>
+                            <property name="LeftDockable">1</property>
+                            <property name="RightDockable">1</property>
+                            <property name="TopDockable">1</property>
+                            <property name="aui_layer">0</property>
+                            <property name="aui_name"></property>
+                            <property name="aui_position">0</property>
+                            <property name="aui_row">0</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="drag_accept_files">0</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">Through vias:</property>
+                            <property name="markup">0</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">staticTextThroughVias</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"></property>
+                            <property name="window_extra_style"></property>
+                            <property name="window_name"></property>
+                            <property name="window_style"></property>
+                            <property name="wrap">-1</property>
+                          </object>
+                        </object>
+                        <object class="sizeritem" expanded="false">
+                          <property name="border">5</property>
+                          <property name="flag">wxALIGN_RIGHT|wxLEFT|wxRIGHT|wxTOP</property>
+                          <property name="proportion">0</property>
+                          <object class="wxStaticText" expanded="false">
+                            <property name="BottomDockable">1</property>
+                            <property name="LeftDockable">1</property>
+                            <property name="RightDockable">1</property>
+                            <property name="TopDockable">1</property>
+                            <property name="aui_layer">0</property>
+                            <property name="aui_name"></property>
+                            <property name="aui_position">0</property>
+                            <property name="aui_row">0</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="drag_accept_files">0</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">0</property>
+                            <property name="markup">0</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_ThroughViasInfoMsg</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"></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"></property>
+                            <property name="wrap">-1</property>
+                          </object>
+                        </object>
+                        <object class="sizeritem" expanded="false">
+                          <property name="border">5</property>
+                          <property name="flag">wxLEFT|wxRIGHT|wxTOP</property>
+                          <property name="proportion">0</property>
+                          <object class="wxStaticText" expanded="false">
+                            <property name="BottomDockable">1</property>
+                            <property name="LeftDockable">1</property>
+                            <property name="RightDockable">1</property>
+                            <property name="TopDockable">1</property>
+                            <property name="aui_layer">0</property>
+                            <property name="aui_name"></property>
+                            <property name="aui_position">0</property>
+                            <property name="aui_row">0</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="drag_accept_files">0</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">Micro vias:</property>
+                            <property name="markup">0</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">staticTextMicroVias</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"></property>
+                            <property name="window_extra_style"></property>
+                            <property name="window_name"></property>
+                            <property name="window_style"></property>
+                            <property name="wrap">-1</property>
+                          </object>
+                        </object>
+                        <object class="sizeritem" expanded="false">
+                          <property name="border">5</property>
+                          <property name="flag">wxALIGN_RIGHT|wxLEFT|wxRIGHT|wxTOP</property>
+                          <property name="proportion">0</property>
+                          <object class="wxStaticText" expanded="false">
+                            <property name="BottomDockable">1</property>
+                            <property name="LeftDockable">1</property>
+                            <property name="RightDockable">1</property>
+                            <property name="TopDockable">1</property>
+                            <property name="aui_layer">0</property>
+                            <property name="aui_name"></property>
+                            <property name="aui_position">0</property>
+                            <property name="aui_row">0</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="drag_accept_files">0</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">0</property>
+                            <property name="markup">0</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_MicroViasInfoMsg</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"></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"></property>
+                            <property name="wrap">-1</property>
+                          </object>
+                        </object>
+                        <object class="sizeritem" expanded="false">
+                          <property name="border">5</property>
+                          <property name="flag">wxALL</property>
+                          <property name="proportion">0</property>
+                          <object class="wxStaticText" expanded="false">
+                            <property name="BottomDockable">1</property>
+                            <property name="LeftDockable">1</property>
+                            <property name="RightDockable">1</property>
+                            <property name="TopDockable">1</property>
+                            <property name="aui_layer">0</property>
+                            <property name="aui_name"></property>
+                            <property name="aui_position">0</property>
+                            <property name="aui_row">0</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="drag_accept_files">0</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">Buried vias:</property>
+                            <property name="markup">0</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">staticTextBuriedVias</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"></property>
+                            <property name="window_extra_style"></property>
+                            <property name="window_name"></property>
+                            <property name="window_style"></property>
+                            <property name="wrap">-1</property>
+                          </object>
+                        </object>
+                        <object class="sizeritem" expanded="false">
+                          <property name="border">5</property>
+                          <property name="flag">wxALIGN_RIGHT|wxALL</property>
+                          <property name="proportion">0</property>
+                          <object class="wxStaticText" expanded="false">
+                            <property name="BottomDockable">1</property>
+                            <property name="LeftDockable">1</property>
+                            <property name="RightDockable">1</property>
+                            <property name="TopDockable">1</property>
+                            <property name="aui_layer">0</property>
+                            <property name="aui_name"></property>
+                            <property name="aui_position">0</property>
+                            <property name="aui_row">0</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="drag_accept_files">0</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">0</property>
+                            <property name="markup">0</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_BuriedViasInfoMsg</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"></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"></property>
+                            <property name="wrap">-1</property>
+                          </object>
+                        </object>
+                      </object>
+                    </object>
+                  </object>
+                </object>
+              </object>
+            </object>
+          </object>
         </object>
+        <object class="sizeritem" expanded="true">
+          <property name="border">5</property>
+          <property name="flag">wxALL|wxEXPAND</property>
+          <property name="proportion">1</property>
+          <object class="wxStaticBoxSizer" expanded="true">
+            <property name="id">wxID_ANY</property>
+            <property name="label">Messages</property>
+            <property name="minimum_size"></property>
+            <property name="name">bMsgSizer</property>
+            <property name="orient">wxVERTICAL</property>
+            <property name="parent">1</property>
+            <property name="permission">protected</property>
+            <object class="sizeritem" expanded="true">
+              <property name="border">5</property>
+              <property name="flag">wxALL|wxEXPAND</property>
+              <property name="proportion">1</property>
+              <object class="wxTextCtrl" expanded="true">
+                <property name="BottomDockable">1</property>
+                <property name="LeftDockable">1</property>
+                <property name="RightDockable">1</property>
+                <property name="TopDockable">1</property>
+                <property name="aui_layer">0</property>
+                <property name="aui_name"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</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="drag_accept_files">0</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="maxlength">0</property>
+                <property name="min_size"></property>
+                <property name="minimize_button">0</property>
+                <property name="minimum_size">-1,90</property>
+                <property name="moveable">1</property>
+                <property name="name">m_messagesBox</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">wxTE_MULTILINE|wxTE_READONLY</property>
+                <property name="subclass"></property>
+                <property name="toolbar_pane">0</property>
+                <property name="tooltip"></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="value"></property>
+                <property name="window_extra_style"></property>
+                <property name="window_name"></property>
+                <property name="window_style"></property>
+              </object>
+            </object>
+          </object>
+        </object>
+        <object class="sizeritem" expanded="true">
+          <property name="border">5</property>
+          <property name="flag">wxALL|wxEXPAND</property>
+          <property name="proportion">0</property>
+          <object class="wxBoxSizer" expanded="true">
+            <property name="minimum_size"></property>
+            <property name="name">m_buttonsSizer</property>
+            <property name="orient">wxHORIZONTAL</property>
+            <property name="permission">protected</property>
+            <object class="sizeritem" expanded="true">
+              <property name="border">10</property>
+              <property name="flag">wxEXPAND|wxRIGHT|wxLEFT</property>
+              <property name="proportion">0</property>
+              <object class="wxButton" expanded="true">
+                <property name="BottomDockable">1</property>
+                <property name="LeftDockable">1</property>
+                <property name="RightDockable">1</property>
+                <property name="TopDockable">1</property>
+                <property name="aui_layer">0</property>
+                <property name="aui_name"></property>
+                <property name="aui_position">0</property>
+                <property name="aui_row">0</property>
+                <property name="auth_needed">0</property>
+                <property name="best_size"></property>
+                <property name="bg"></property>
+                <property name="bitmap"></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="current"></property>
+                <property name="default">0</property>
+                <property name="default_pane">0</property>
+                <property name="disabled"></property>
+                <property name="dock">Dock</property>
+                <property name="dock_fixed">0</property>
+                <property name="docking">Left</property>
+                <property name="drag_accept_files">0</property>
+                <property name="enabled">1</property>
+                <property name="fg"></property>
+                <property name="floatable">1</property>
+                <property name="focus"></property>
+                <property name="font"></property>
+                <property name="gripper">0</property>
+                <property name="hidden">0</property>
+                <property name="id">wxID_ANY</property>
+                <property name="label">Generate Report File...</property>
+                <property name="margins"></property>
+                <property name="markup">0</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_buttonReport</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="position"></property>
+                <property name="pressed"></property>
+                <property name="resize">Resizable</property>
+                <property name="show">1</property>
+                <property name="size"></property>
+                <property name="style"></property>
+                <property name="subclass"></property>
+                <property name="toolbar_pane">0</property>
+                <property name="tooltip"></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="OnButtonClick">OnGenReportFile</event>
+              </object>
+            </object>
+            <object class="sizeritem" expanded="true">
+              <property name="border">5</property>
+              <property name="flag">wxEXPAND</property>
+              <property name="proportion">1</property>
+              <object class="wxStdDialogButtonSizer" expanded="true">
+                <property name="Apply">1</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_sdbSizer</property>
+                <property name="permission">protected</property>
+                <event name="OnApplyButtonClick">OnGenMapFile</event>
+                <event name="OnCancelButtonClick">onQuitDlg</event>
+                <event name="OnOKButtonClick">OnGenDrillFile</event>
+              </object>
+            </object>
+          </object>
+        </object>
+      </object>
     </object>
+  </object>
 </wxFormBuilder_Project>
diff --git a/pcbnew/dialogs/dialog_gendrill_base.h b/pcbnew/dialogs/dialog_gendrill_base.h
index 5d16421bbd..1a96e31374 100644
--- a/pcbnew/dialogs/dialog_gendrill_base.h
+++ b/pcbnew/dialogs/dialog_gendrill_base.h
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////
-// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b)
+// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
 // http://www.wxformbuilder.org/
 //
 // PLEASE DO *NOT* EDIT THIS FILE!
@@ -34,7 +34,6 @@ class STD_BITMAP_BUTTON;
 
 ///////////////////////////////////////////////////////////////////////////
 
-
 ///////////////////////////////////////////////////////////////////////////////
 /// Class DIALOG_GENDRILL_BASE
 ///////////////////////////////////////////////////////////////////////////////
@@ -43,6 +42,7 @@ class DIALOG_GENDRILL_BASE : public DIALOG_SHIM
 	private:
 
 	protected:
+		wxBoxSizer* bMainSizer;
 		wxStaticText* staticTextOutputDir;
 		wxTextCtrl* m_outputDirectoryName;
 		STD_BITMAP_BUTTON* m_browseButton;
@@ -68,6 +68,7 @@ class DIALOG_GENDRILL_BASE : public DIALOG_SHIM
 		wxStaticText* m_MicroViasInfoMsg;
 		wxStaticText* staticTextBuriedVias;
 		wxStaticText* m_BuriedViasInfoMsg;
+		wxStaticBoxSizer* bMsgSizer;
 		wxTextCtrl* m_messagesBox;
 		wxBoxSizer* m_buttonsSizer;
 		wxButton* m_buttonReport;
diff --git a/pcbnew/dialogs/dialog_plot.cpp b/pcbnew/dialogs/dialog_plot.cpp
index a5d5a8e4e1..c625d32ab8 100644
--- a/pcbnew/dialogs/dialog_plot.cpp
+++ b/pcbnew/dialogs/dialog_plot.cpp
@@ -46,6 +46,9 @@
 #include <tools/drc_tool.h>
 #include <math/util.h>      // for KiROUND
 #include <macros.h>
+#include <jobs/job_export_pcb_gerbers.h>
+#include <jobs/job_export_pcb_dxf.h>
+#include <jobs/job_export_pcb_pdf.h>
 
 #include <wx/dirdlg.h>
 #include <wx/msgdlg.h>
@@ -84,19 +87,39 @@ PCB_LAYER_ID_CLIENT_DATA* getLayerClientData( const wxRearrangeList* aList, int
 }
 
 
-DIALOG_PLOT::DIALOG_PLOT( PCB_EDIT_FRAME* aParent ) :
-    DIALOG_PLOT_BASE( aParent ),
-    m_parent( aParent ),
-    m_defaultPenSize( aParent, m_hpglPenLabel, m_hpglPenCtrl, m_hpglPenUnits ),
-    m_trackWidthCorrection( aParent, m_widthAdjustLabel, m_widthAdjustCtrl, m_widthAdjustUnits )
+DIALOG_PLOT::DIALOG_PLOT( PCB_EDIT_FRAME* aEditFrame )
+    : DIALOG_PLOT( aEditFrame, aEditFrame )
 {
-    BOARD* board = m_parent->GetBoard();
+}
+
+
+DIALOG_PLOT::DIALOG_PLOT( PCB_EDIT_FRAME* aEditFrame, wxWindow* aParent,
+                          JOB_EXPORT_PCB_PLOT* aJob ) :
+    DIALOG_PLOT_BASE( aParent ),
+    m_editFrame( aEditFrame ),
+    m_defaultPenSize( m_editFrame, m_hpglPenLabel, m_hpglPenCtrl, m_hpglPenUnits ),
+    m_trackWidthCorrection( m_editFrame, m_widthAdjustLabel, m_widthAdjustCtrl, m_widthAdjustUnits ),
+    m_job( aJob )
+{
+    BOARD* board = m_editFrame->GetBoard();
 
     SetName( DLG_WINDOW_NAME );
-    m_plotOpts = aParent->GetPlotSettings();
+    m_plotOpts = m_editFrame->GetPlotSettings();
     m_DRCWarningTemplate = m_DRCExclusionsWarning->GetLabel();
 
-    m_messagesPanel->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
+    if( m_job )
+    {
+        m_messagesPanel->Hide();
+
+        m_browseButton->Hide();
+        m_staticTextPlotFmt->Hide();
+        m_plotFormatOpt->Hide();
+        m_sdbSizer1Apply->Hide();
+    }
+    else
+    {
+        m_messagesPanel->SetFileName( Prj().GetProjectPath() + wxT( "report.txt" ) );
+    }
 
     int                       order = 0;
     LSET                      plotOnAllLayersSelection = m_plotOpts.GetPlotOnAllLayersSelection();
@@ -185,9 +208,17 @@ DIALOG_PLOT::DIALOG_PLOT( PCB_EDIT_FRAME* aParent ) :
 
     init_Dialog();
 
-    SetupStandardButtons( { { wxID_OK,     _( "Plot" )                    },
-                            { wxID_APPLY,  _( "Generate Drill Files..." ) },
-                            { wxID_CANCEL, _( "Close" )                   } } );
+    if( m_job )
+    {
+        SetupStandardButtons( { { wxID_OK, _( "Save" ) },
+                                { wxID_CANCEL, _( "Close" ) } } );
+    }
+    else
+    {
+        SetupStandardButtons( { { wxID_OK, _( "Plot" ) },
+                                { wxID_APPLY, _( "Generate Drill Files..." ) },
+                                { wxID_CANCEL, _( "Close" ) } } );
+    }
 
     GetSizer()->Fit( this );
     GetSizer()->SetSizeHints( this );
@@ -219,165 +250,183 @@ DIALOG_PLOT::~DIALOG_PLOT()
 
 void DIALOG_PLOT::init_Dialog()
 {
-    BOARD*      board = m_parent->GetBoard();
+    BOARD*      board = m_editFrame->GetBoard();
     wxFileName  fileName;
 
-    PROJECT_FILE&    projectFile = m_parent->Prj().GetProjectFile();
-    PCBNEW_SETTINGS* cfg = m_parent->GetPcbNewSettings();
-
-    if( !projectFile.m_PcbLastPath[ LAST_PATH_PLOT ].IsEmpty() )
-        m_plotOpts.SetOutputDirectory( projectFile.m_PcbLastPath[ LAST_PATH_PLOT ] );
-
-    m_XScaleAdjust = cfg->m_Plot.fine_scale_x;
-    m_YScaleAdjust = cfg->m_Plot.fine_scale_y;
-
-    m_zoneFillCheck->SetValue( cfg->m_Plot.check_zones_before_plotting );
-
-    m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
-
-    // m_PSWidthAdjust is stored in mm in user config
-    m_PSWidthAdjust = KiROUND( cfg->m_Plot.ps_fine_width_adjust * pcbIUScale.IU_PER_MM );
-
-    // The reasonable width correction value must be in a range of
-    // [-(MinTrackWidth-1), +(MinClearanceValue-1)] decimils.
-    m_widthAdjustMinValue   = -( board->GetDesignSettings().m_TrackMinWidth - 1 );
-    m_widthAdjustMaxValue   = board->GetDesignSettings().GetSmallestClearanceValue() - 1;
-
-    switch( m_plotOpts.GetFormat() )
-    {
-    default:
-    case PLOT_FORMAT::GERBER: m_plotFormatOpt->SetSelection( 0 ); break;
-    case PLOT_FORMAT::POST:   m_plotFormatOpt->SetSelection( 1 ); break;
-    case PLOT_FORMAT::SVG:    m_plotFormatOpt->SetSelection( 2 ); break;
-    case PLOT_FORMAT::DXF:    m_plotFormatOpt->SetSelection( 3 ); break;
-    case PLOT_FORMAT::HPGL:   m_plotFormatOpt->SetSelection( 4 ); break;
-    case PLOT_FORMAT::PDF:    m_plotFormatOpt->SetSelection( 5 ); break;
-    }
-
-    // Set units and value for HPGL pen size (this param is in mils).
-    m_defaultPenSize.SetValue( m_plotOpts.GetHPGLPenDiameter() * pcbIUScale.IU_PER_MILS );
-
-    // Test for a reasonable scale value. Set to 1 if problem
-    if( m_XScaleAdjust < PLOT_MIN_SCALE || m_YScaleAdjust < PLOT_MIN_SCALE
-        || m_XScaleAdjust > PLOT_MAX_SCALE || m_YScaleAdjust > PLOT_MAX_SCALE )
-    {
-        m_XScaleAdjust = m_YScaleAdjust = 1.0;
-    }
-
-    m_fineAdjustXCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( unityScale,
-                                                                      EDA_UNITS::UNSCALED,
-                                                                      m_XScaleAdjust ) );
-
-    m_fineAdjustYCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue( unityScale,
-                                                                      EDA_UNITS::UNSCALED,
-                                                                      m_YScaleAdjust ) );
-
-    // Test for a reasonable PS width correction value. Set to 0 if problem.
-    if( m_PSWidthAdjust < m_widthAdjustMinValue || m_PSWidthAdjust > m_widthAdjustMaxValue )
-        m_PSWidthAdjust = 0.;
-
-    m_trackWidthCorrection.SetValue( m_PSWidthAdjust );
-
-    m_plotPSNegativeOpt->SetValue( m_plotOpts.GetNegative() );
-    m_forcePSA4OutputOpt->SetValue( m_plotOpts.GetA4Output() );
+    PROJECT_FILE& projectFile = m_editFrame->Prj().GetProjectFile();
 
     // Could devote a PlotOrder() function in place of UIOrder().
     m_layerList = board->GetEnabledLayers().UIOrder();
 
-    // Populate the check list box by all enabled layers names.
-    for( PCB_LAYER_ID layer : m_layerList )
+    if( !m_job )
     {
-        int checkIndex = m_layerCheckListBox->Append( board->GetLayerName( layer ) );
+        PCBNEW_SETTINGS* cfg = m_editFrame->GetPcbNewSettings();
 
-        if( m_plotOpts.GetLayerSelection()[layer] )
-            m_layerCheckListBox->Check( checkIndex );
+        if( !projectFile.m_PcbLastPath[ LAST_PATH_PLOT ].IsEmpty() )
+            m_plotOpts.SetOutputDirectory( projectFile.m_PcbLastPath[ LAST_PATH_PLOT ] );
+
+        m_XScaleAdjust = cfg->m_Plot.fine_scale_x;
+        m_YScaleAdjust = cfg->m_Plot.fine_scale_y;
+
+        m_zoneFillCheck->SetValue( cfg->m_Plot.check_zones_before_plotting );
+
+        m_browseButton->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
+
+        // m_PSWidthAdjust is stored in mm in user config
+        m_PSWidthAdjust = KiROUND( cfg->m_Plot.ps_fine_width_adjust * pcbIUScale.IU_PER_MM );
+
+        // The reasonable width correction value must be in a range of
+        // [-(MinTrackWidth-1), +(MinClearanceValue-1)] decimils.
+        m_widthAdjustMinValue   = -( board->GetDesignSettings().m_TrackMinWidth - 1 );
+        m_widthAdjustMaxValue   = board->GetDesignSettings().GetSmallestClearanceValue() - 1;
+
+        switch( m_plotOpts.GetFormat() )
+        {
+        default:
+        case PLOT_FORMAT::GERBER: m_plotFormatOpt->SetSelection( 0 ); break;
+        case PLOT_FORMAT::POST:   m_plotFormatOpt->SetSelection( 1 ); break;
+        case PLOT_FORMAT::SVG:    m_plotFormatOpt->SetSelection( 2 ); break;
+        case PLOT_FORMAT::DXF:    m_plotFormatOpt->SetSelection( 3 ); break;
+        case PLOT_FORMAT::HPGL:   m_plotFormatOpt->SetSelection( 4 ); break;
+        case PLOT_FORMAT::PDF:    m_plotFormatOpt->SetSelection( 5 ); break;
+        }
+
+        // Set units and value for HPGL pen size (this param is in mils).
+        m_defaultPenSize.SetValue( m_plotOpts.GetHPGLPenDiameter() * pcbIUScale.IU_PER_MILS );
+
+        // Test for a reasonable scale value. Set to 1 if problem
+        if( m_XScaleAdjust < PLOT_MIN_SCALE || m_YScaleAdjust < PLOT_MIN_SCALE
+            || m_XScaleAdjust > PLOT_MAX_SCALE || m_YScaleAdjust > PLOT_MAX_SCALE )
+        {
+            m_XScaleAdjust = m_YScaleAdjust = 1.0;
+        }
+
+        m_fineAdjustXCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue(
+                unityScale, EDA_UNITS::UNSCALED, m_XScaleAdjust ) );
+
+        m_fineAdjustYCtrl->SetValue( EDA_UNIT_UTILS::UI::StringFromValue(
+                unityScale, EDA_UNITS::UNSCALED, m_YScaleAdjust ) );
+
+        // Test for a reasonable PS width correction value. Set to 0 if problem.
+        if( m_PSWidthAdjust < m_widthAdjustMinValue || m_PSWidthAdjust > m_widthAdjustMaxValue )
+            m_PSWidthAdjust = 0.;
+
+        m_trackWidthCorrection.SetValue( m_PSWidthAdjust );
+
+        m_plotPSNegativeOpt->SetValue( m_plotOpts.GetNegative() );
+        m_forcePSA4OutputOpt->SetValue( m_plotOpts.GetA4Output() );
+
+        // Populate the check list box by all enabled layers names.
+        for( PCB_LAYER_ID layer : m_layerList )
+        {
+            int checkIndex = m_layerCheckListBox->Append( board->GetLayerName( layer ) );
+
+            if( m_plotOpts.GetLayerSelection()[layer] )
+                m_layerCheckListBox->Check( checkIndex );
+        }
+
+        arrangeAllLayersList( s_lastAllLayersOrder );
+
+        // Option for disabling Gerber Aperture Macro (for broken Gerber readers)
+        m_disableApertMacros->SetValue( m_plotOpts.GetDisableGerberMacros() );
+
+        // Option for using proper Gerber extensions. Note also Protel extensions are
+        // a broken feature. However, for now, we need to handle it.
+        m_useGerberExtensions->SetValue( m_plotOpts.GetUseGerberProtelExtensions() );
+
+        // Option for including Gerber attributes, from Gerber X2 format, in the output
+        // In X1 format, they will be added as comments
+        m_useGerberX2Format->SetValue( m_plotOpts.GetUseGerberX2format() );
+
+        // Option for including Gerber netlist info (from Gerber X2 format) in the output
+        m_useGerberNetAttributes->SetValue( m_plotOpts.GetIncludeGerberNetlistInfo() );
+
+        // Option to generate a Gerber job file
+        m_generateGerberJobFile->SetValue( m_plotOpts.GetCreateGerberJobFile() );
+
+        // Gerber precision for coordinates
+        m_coordFormatCtrl->SetSelection( m_plotOpts.GetGerberPrecision() == 5 ? 0 : 1 );
+
+        // SVG precision and units for coordinates
+        m_svgPrecsision->SetValue( m_plotOpts.GetSvgPrecision() );
+
+        // Option to exclude pads from silkscreen layers
+        m_sketchPadsOnFabLayers->SetValue( m_plotOpts.GetSketchPadsOnFabLayers() );
+        m_plotPadNumbers->SetValue( m_plotOpts.GetPlotPadNumbers() );
+        m_plotPadNumbers->Enable( m_plotOpts.GetSketchPadsOnFabLayers() );
+
+        m_plotDNP->SetValue( m_plotOpts.GetHideDNPFPsOnFabLayers()
+                             || m_plotOpts.GetSketchDNPFPsOnFabLayers()
+                             || m_plotOpts.GetCrossoutDNPFPsOnFabLayers() );
+
+        if( m_plotDNP->GetValue() )
+        {
+            if( m_plotOpts.GetHideDNPFPsOnFabLayers() )
+                m_hideDNP->SetValue( true );
+            else
+                m_crossoutDNP->SetValue( true );
+        }
+
+        m_hideDNP->Enable( m_plotDNP->GetValue() );
+        m_crossoutDNP->Enable( m_plotDNP->GetValue() );
+
+        // Option to tent vias
+        m_subtractMaskFromSilk->SetValue( m_plotOpts.GetSubtractMaskFromSilk() );
+
+        // Option to use aux origin
+        m_useAuxOriginCheckBox->SetValue( m_plotOpts.GetUseAuxOrigin() );
+
+        // Option to plot page references:
+        m_plotSheetRef->SetValue( m_plotOpts.GetPlotFrameRef() );
+
+        // Option to force ploting of hidden text in footprints
+        m_plotInvisibleText->SetValue( m_plotOpts.GetPlotInvisibleText() );
+
+        // Options to plot pads and vias holes
+        m_drillShapeOpt->SetSelection( (int) m_plotOpts.GetDrillMarksType() );
+
+        // Scale option
+        m_scaleOpt->SetSelection( m_plotOpts.GetScaleSelection() );
+
+        // Plot mode
+        setPlotModeChoiceSelection( m_plotOpts.GetPlotMode() );
+
+        // DXF outline mode
+        m_DXF_plotModeOpt->SetValue( m_plotOpts.GetDXFPlotPolygonMode() );
+
+        // DXF text mode
+        m_DXF_plotTextStrokeFontOpt->SetValue( m_plotOpts.GetTextMode()
+                                               == PLOT_TEXT_MODE::DEFAULT );
+
+        // DXF units selection
+        m_DXF_plotUnits->SetSelection( m_plotOpts.GetDXFPlotUnits() == DXF_UNITS::INCHES ? 0 : 1 );
+
+        // Plot mirror option
+        m_plotMirrorOpt->SetValue( m_plotOpts.GetMirror() );
+
+        // Black and white plotting
+        m_SVGColorChoice->SetSelection( m_plotOpts.GetBlackAndWhite() ? 1 : 0 );
+        m_PDFColorChoice->SetSelection( m_plotOpts.GetBlackAndWhite() ? 1 : 0 );
+        m_frontFPPropertyPopups->SetValue( m_plotOpts.m_PDFFrontFPPropertyPopups );
+        m_backFPPropertyPopups->SetValue( m_plotOpts.m_PDFBackFPPropertyPopups );
+        m_pdfMetadata->SetValue( m_plotOpts.m_PDFMetadata );
     }
-
-    arrangeAllLayersList( s_lastAllLayersOrder );
-
-    // Option for disabling Gerber Aperture Macro (for broken Gerber readers)
-    m_disableApertMacros->SetValue( m_plotOpts.GetDisableGerberMacros() );
-
-    // Option for using proper Gerber extensions. Note also Protel extensions are
-    // a broken feature. However, for now, we need to handle it.
-    m_useGerberExtensions->SetValue( m_plotOpts.GetUseGerberProtelExtensions() );
-
-    // Option for including Gerber attributes, from Gerber X2 format, in the output
-    // In X1 format, they will be added as comments
-    m_useGerberX2Format->SetValue( m_plotOpts.GetUseGerberX2format() );
-
-    // Option for including Gerber netlist info (from Gerber X2 format) in the output
-    m_useGerberNetAttributes->SetValue( m_plotOpts.GetIncludeGerberNetlistInfo() );
-
-    // Option to generate a Gerber job file
-    m_generateGerberJobFile->SetValue( m_plotOpts.GetCreateGerberJobFile() );
-
-    // Gerber precision for coordinates
-    m_coordFormatCtrl->SetSelection( m_plotOpts.GetGerberPrecision() == 5 ? 0 : 1 );
-
-    // SVG precision and units for coordinates
-    m_svgPrecsision->SetValue( m_plotOpts.GetSvgPrecision() );
-
-    // Option to exclude pads from silkscreen layers
-    m_sketchPadsOnFabLayers->SetValue( m_plotOpts.GetSketchPadsOnFabLayers() );
-    m_plotPadNumbers->SetValue( m_plotOpts.GetPlotPadNumbers() );
-    m_plotPadNumbers->Enable( m_plotOpts.GetSketchPadsOnFabLayers() );
-
-    m_plotDNP->SetValue( m_plotOpts.GetHideDNPFPsOnFabLayers()
-                            || m_plotOpts.GetSketchDNPFPsOnFabLayers()
-                            || m_plotOpts.GetCrossoutDNPFPsOnFabLayers() );
-
-    if( m_plotDNP->GetValue() )
+    else
     {
-        if( m_plotOpts.GetHideDNPFPsOnFabLayers() )
-            m_hideDNP->SetValue( true );
-        else
-            m_crossoutDNP->SetValue( true );
+        m_plotFormatOpt->Hide();
+
+        switch( m_job->m_plotFormat )
+        {
+        default:
+        case JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::GERBER: m_plotFormatOpt->SetSelection( 0 ); break;
+        case JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::POST: m_plotFormatOpt->SetSelection( 1 ); break;
+        case JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::SVG: m_plotFormatOpt->SetSelection( 2 ); break;
+        case JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::DXF: m_plotFormatOpt->SetSelection( 3 ); break;
+        case JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::HPGL: m_plotFormatOpt->SetSelection( 4 ); break;
+        case JOB_EXPORT_PCB_PLOT::PLOT_FORMAT::PDF: m_plotFormatOpt->SetSelection( 5 ); break;
+        }
     }
 
-    m_hideDNP->Enable( m_plotDNP->GetValue() );
-    m_crossoutDNP->Enable( m_plotDNP->GetValue() );
-
-    // Option to tent vias
-    m_subtractMaskFromSilk->SetValue( m_plotOpts.GetSubtractMaskFromSilk() );
-
-    // Option to use aux origin
-    m_useAuxOriginCheckBox->SetValue( m_plotOpts.GetUseAuxOrigin() );
-
-    // Option to plot page references:
-    m_plotSheetRef->SetValue( m_plotOpts.GetPlotFrameRef() );
-
-    // Option to force ploting of hidden text in footprints
-    m_plotInvisibleText->SetValue( m_plotOpts.GetPlotInvisibleText() );
-
-    // Options to plot pads and vias holes
-    m_drillShapeOpt->SetSelection( (int)m_plotOpts.GetDrillMarksType() );
-
-    // Scale option
-    m_scaleOpt->SetSelection( m_plotOpts.GetScaleSelection() );
-
-    // Plot mode
-    setPlotModeChoiceSelection( m_plotOpts.GetPlotMode() );
-
-    // DXF outline mode
-    m_DXF_plotModeOpt->SetValue( m_plotOpts.GetDXFPlotPolygonMode() );
-
-    // DXF text mode
-    m_DXF_plotTextStrokeFontOpt->SetValue( m_plotOpts.GetTextMode() == PLOT_TEXT_MODE::DEFAULT );
-
-    // DXF units selection
-    m_DXF_plotUnits->SetSelection( m_plotOpts.GetDXFPlotUnits() == DXF_UNITS::INCHES ? 0 : 1);
-
-    // Plot mirror option
-    m_plotMirrorOpt->SetValue( m_plotOpts.GetMirror() );
-
-    // Black and white plotting
-    m_SVGColorChoice->SetSelection( m_plotOpts.GetBlackAndWhite() ? 1 : 0 );
-    m_PDFColorChoice->SetSelection( m_plotOpts.GetBlackAndWhite() ? 1 : 0 );
-    m_frontFPPropertyPopups->SetValue( m_plotOpts.m_PDFFrontFPPropertyPopups );
-    m_backFPPropertyPopups->SetValue( m_plotOpts.m_PDFBackFPPropertyPopups );
-    m_pdfMetadata->SetValue( m_plotOpts.m_PDFMetadata );
-
     // Initialize a few other parameters, which can also be modified
     // from the drill dialog
     reInitDialog();
@@ -402,7 +451,7 @@ void DIALOG_PLOT::reInitDialog()
     int knownViolations = 0;
     int exclusions = 0;
 
-    for( PCB_MARKER* marker : m_parent->GetBoard()->Markers() )
+    for( PCB_MARKER* marker : m_editFrame->GetBoard()->Markers() )
     {
         if( marker->GetSeverity() == RPT_SEVERITY_EXCLUSION )
             exclusions++;
@@ -421,7 +470,7 @@ void DIALOG_PLOT::reInitDialog()
         m_DRCExclusionsWarning->Hide();
     }
 
-    BOARD* board = m_parent->GetBoard();
+    BOARD* board = m_editFrame->GetBoard();
     const BOARD_DESIGN_SETTINGS& brd_settings = board->GetDesignSettings();
 
     if( getPlotFormat() == PLOT_FORMAT::GERBER &&
@@ -578,7 +627,7 @@ void DIALOG_PLOT::OnRightClickAllLayers( wxMouseEvent& event )
 
                 case ID_STACKUP_ORDER:
                 {
-                    LSEQ stackup = m_parent->GetBoard()->GetEnabledLayers().SeqStackupForPlotting();
+                    LSEQ stackup = m_editFrame->GetBoard()->GetEnabledLayers().SeqStackupForPlotting();
                     arrangeAllLayersList( stackup );
                     m_plotAllLayersList->Select( -1 );
                     break;
@@ -598,11 +647,11 @@ void DIALOG_PLOT::CreateDrillFile( wxCommandEvent& event )
     // Be sure drill file use the same settings (axis option, plot directory) as plot files:
     applyPlotSettings();
 
-    DIALOG_GENDRILL dlg( m_parent, this );
+    DIALOG_GENDRILL dlg( m_editFrame, this );
     dlg.ShowModal();
 
     // a few plot settings can be modified: take them in account
-    m_plotOpts = m_parent->GetPlotSettings();
+    m_plotOpts = m_editFrame->GetPlotSettings();
     reInitDialog();
 }
 
@@ -638,7 +687,7 @@ void DIALOG_PLOT::OnOutputDirectoryBrowseClicked( wxCommandEvent& event )
     std::function<bool( wxString* )> textResolver =
             [&]( wxString* token ) -> bool
             {
-                return m_parent->GetBoard()->ResolveTextVar( token, 0 );
+                return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
             };
 
     wxString path = m_outputDirectoryName->GetValue();
@@ -653,7 +702,7 @@ void DIALOG_PLOT::OnOutputDirectoryBrowseClicked( wxCommandEvent& event )
 
     wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
 
-    wxFileName fn( Prj().AbsolutePath( m_parent->GetBoard()->GetFileName() ) );
+    wxFileName fn( Prj().AbsolutePath( m_editFrame->GetBoard()->GetFileName() ) );
     wxString   defaultPath = fn.GetPathWithSep();
     wxString   msg;
     wxFileName relPathTest; // Used to test if we can make the path relative
@@ -698,7 +747,7 @@ void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event )
 
     // The alert message about non 0 solder mask min width and margin is shown
     // only in gerber format and if min mask width or mask margin is not 0
-    BOARD* board = m_parent->GetBoard();
+    BOARD* board = m_editFrame->GetBoard();
     const BOARD_DESIGN_SETTINGS& brd_settings = board->GetDesignSettings();
 
     if( getPlotFormat() == PLOT_FORMAT::GERBER
@@ -996,7 +1045,7 @@ void DIALOG_PLOT::applyPlotSettings()
         reporter.Report( msg, RPT_SEVERITY_INFO );
     }
 
-    auto cfg = m_parent->GetPcbNewSettings();
+    auto cfg = m_editFrame->GetPcbNewSettings();
 
     cfg->m_Plot.fine_scale_x = m_XScaleAdjust;
     cfg->m_Plot.fine_scale_y = m_YScaleAdjust;
@@ -1010,8 +1059,8 @@ void DIALOG_PLOT::applyPlotSettings()
         m_trackWidthCorrection.SetValue( m_PSWidthAdjust );
         msg.Printf( _( "Width correction constrained.  The width correction value must be in the"
                        " range of [%s; %s] for the current design rules." ),
-                    m_parent->StringFromValue( m_widthAdjustMinValue, true ),
-                    m_parent->StringFromValue( m_widthAdjustMaxValue, true ) );
+                    m_editFrame->StringFromValue( m_widthAdjustMinValue, true ),
+                    m_editFrame->StringFromValue( m_widthAdjustMaxValue, true ) );
         reporter.Report( msg, RPT_SEVERITY_WARNING );
     }
 
@@ -1038,7 +1087,7 @@ void DIALOG_PLOT::applyPlotSettings()
     }
 
     // Get a list of copper layers that aren't being used by inverting enabled layers.
-    LSET disabledCopperLayers = LSET::AllCuMask() & ~m_parent->GetBoard()->GetEnabledLayers();
+    LSET disabledCopperLayers = LSET::AllCuMask() & ~m_editFrame->GetBoard()->GetEnabledLayers();
 
     LSET plotOnAllLayers;
 
@@ -1075,12 +1124,12 @@ void DIALOG_PLOT::applyPlotSettings()
     dirStr = m_outputDirectoryName->GetValue();
     dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
     tempOptions.SetOutputDirectory( dirStr );
-    m_parent->Prj().GetProjectFile().m_PcbLastPath[ LAST_PATH_PLOT ] = dirStr;
+    m_editFrame->Prj().GetProjectFile().m_PcbLastPath[ LAST_PATH_PLOT ] = dirStr;
 
     if( !m_plotOpts.IsSameAs( tempOptions ) )
     {
-        m_parent->SetPlotSettings( tempOptions );
-        m_parent->OnModify();
+        m_editFrame->SetPlotSettings( tempOptions );
+        m_editFrame->OnModify();
         m_plotOpts = tempOptions;
     }
 }
@@ -1092,209 +1141,228 @@ void DIALOG_PLOT::OnGerberX2Checked( wxCommandEvent& event )
 }
 
 
+void DIALOG_PLOT::updateJobFromDialog()
+{
+    m_job->m_mirror = m_plotMirrorOpt->GetValue();
+    m_job->m_plotDrawingSheet = m_plotSheetRef->GetValue();
+    m_job->m_hideDNPFPsOnFabLayers = m_plotDNP->GetValue() && m_hideDNP->GetValue();
+    m_job->m_sketchDNPFPsOnFabLayers = m_plotDNP->GetValue() && m_crossoutDNP->GetValue();
+    m_job->m_crossoutDNPFPsOnFabLayers = m_plotDNP->GetValue() && m_crossoutDNP->GetValue();
+    //m_job->m_plotInvisibleText = m_plotInvisibleText->GetValue();
+    m_job->m_drillShapeOption = static_cast<int>( m_drillShapeOpt->GetSelection() );
+}
+
+
 void DIALOG_PLOT::Plot( wxCommandEvent& event )
 {
-    BOARD* board = m_parent->GetBoard();
-
-    applyPlotSettings();
-
-    SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
-    PCBNEW_SETTINGS*  cfg = mgr.GetAppSettings<PCBNEW_SETTINGS>();
-
-    m_plotOpts.SetColorSettings( mgr.GetColorSettings( cfg->m_ColorTheme ) );
-
-    m_plotOpts.SetSketchPadLineWidth( board->GetDesignSettings().GetLineThickness( F_Fab ) );
-
-    // If no layer selected, we have nothing plotted.
-    // Prompt user if it happens because he could think there is a bug in Pcbnew.
-    if( !m_plotOpts.GetLayerSelection().any() )
+    if( m_job )
     {
-        DisplayError( this, _( "No layer selected, Nothing to plot" ) );
-        return;
+        updateJobFromDialog();
     }
-
-    // Create output directory if it does not exist (also transform it in absolute form).
-    // Bail if it fails.
-
-    std::function<bool( wxString* )> textResolver =
-            [&]( wxString* token ) -> bool
-            {
-                // Handles board->GetTitleBlock() *and* board->GetProject()
-                return m_parent->GetBoard()->ResolveTextVar( token, 0 );
-            };
-
-    wxString path = m_plotOpts.GetOutputDirectory();
-    path = ExpandTextVars( path, &textResolver );
-    path = ExpandEnvVarSubstitutions( path, board->GetProject() );
-
-    wxFileName outputDir = wxFileName::DirName( path );
-    wxString   boardFilename = m_parent->GetBoard()->GetFileName();
-    REPORTER&  reporter = m_messagesPanel->Reporter();
-
-    if( !EnsureFileDirectoryExists( &outputDir, boardFilename, &reporter ) )
+    else
     {
-        wxString msg;
-        msg.Printf( _( "Could not write plot files to folder '%s'." ), outputDir.GetPath() );
-        DisplayError( this, msg );
-        return;
-    }
+        BOARD* board = m_editFrame->GetBoard();
 
-    if( m_zoneFillCheck->GetValue() )
-        m_parent->GetToolManager()->GetTool<ZONE_FILLER_TOOL>()->CheckAllZones( this );
+        applyPlotSettings();
 
-    m_plotOpts.SetAutoScale( false );
+        SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
+        PCBNEW_SETTINGS*  cfg = mgr.GetAppSettings<PCBNEW_SETTINGS>();
 
-    switch( m_plotOpts.GetScaleSelection() )
-    {
-    default: m_plotOpts.SetScale( 1 );        break;
-    case 0:  m_plotOpts.SetAutoScale( true ); break;
-    case 2:  m_plotOpts.SetScale( 1.5 );      break;
-    case 3:  m_plotOpts.SetScale( 2 );        break;
-    case 4:  m_plotOpts.SetScale( 3 );        break;
-    }
+        m_plotOpts.SetColorSettings( mgr.GetColorSettings( cfg->m_ColorTheme ) );
 
-    /* If the scale factor edit controls are disabled or the scale value
-     * is 0, don't adjust the base scale factor. This fixes a bug when
-     * the default scale adjust is initialized to 0 and saved in program
-     * settings resulting in a divide by zero fault.
-     */
-    if( getPlotFormat() == PLOT_FORMAT::POST )
-    {
-        if( m_XScaleAdjust != 0.0 )
-            m_plotOpts.SetFineScaleAdjustX( m_XScaleAdjust );
+        m_plotOpts.SetSketchPadLineWidth( board->GetDesignSettings().GetLineThickness( F_Fab ) );
 
-        if( m_YScaleAdjust != 0.0 )
-            m_plotOpts.SetFineScaleAdjustY( m_YScaleAdjust );
-
-        m_plotOpts.SetWidthAdjust( m_PSWidthAdjust );
-    }
-
-    wxString file_ext( GetDefaultPlotExtension( m_plotOpts.GetFormat() ) );
-
-    // Test for a reasonable scale value
-    // XXX could this actually happen? isn't it constrained in the apply function?
-    if( m_plotOpts.GetScale() < PLOT_MIN_SCALE )
-        DisplayInfoMessage( this, _( "Warning: Scale option set to a very small value" ) );
-
-    if( m_plotOpts.GetScale() > PLOT_MAX_SCALE )
-        DisplayInfoMessage( this, _( "Warning: Scale option set to a very large value" ) );
-
-    GERBER_JOBFILE_WRITER jobfile_writer( board, &reporter );
-
-    // Save the current plot options in the board
-    m_parent->SetPlotSettings( m_plotOpts );
-
-    wxBusyCursor dummy;
-
-    for( PCB_LAYER_ID layer : m_plotOpts.GetLayerSelection().UIOrder() )
-    {
-        LSEQ plotSequence;
-
-        // Base layer always gets plotted first.
-        plotSequence.push_back( layer );
-
-        // Add selected layers from plot on all layers list in order set by user.
-        wxArrayInt plotOnAllLayers;
-
-        if( m_plotAllLayersList->GetCheckedItems( plotOnAllLayers ) )
+        // If no layer selected, we have nothing plotted.
+        // Prompt user if it happens because he could think there is a bug in Pcbnew.
+        if( !m_plotOpts.GetLayerSelection().any() )
         {
-            size_t count = plotOnAllLayers.GetCount();
-
-            for( size_t i = 0; i < count; i++ )
-            {
-                int index = plotOnAllLayers.Item( i );
-                PCB_LAYER_ID client_layer = getLayerClientData( m_plotAllLayersList, index )->Layer();
-
-                // Don't plot the same layer more than once;
-                if( find( plotSequence.begin(), plotSequence.end(), client_layer ) != plotSequence.end() )
-                    continue;
-
-                plotSequence.push_back( client_layer );
-            }
+            DisplayError( this, _( "No layer selected, Nothing to plot" ) );
+            return;
         }
 
-        wxString     layerName = board->GetLayerName( layer );
-        //@todo allow controlling the sheet name and path that will be displayed in the title block
-        // Leave blank for now
-        wxString     sheetName;
-        wxString     sheetPath;
+        // Create output directory if it does not exist (also transform it in absolute form).
+        // Bail if it fails.
 
-        // All copper layers that are disabled are actually selected
-        // This is due to wonkyness in automatically selecting copper layers
-        // for plotting when adding more than two layers to a board.
-        // If plot options become accessible to the layers setup dialog
-        // please move this functionality there!
-        // This skips a copper layer if it is actually disabled on the board.
-        if( ( LSET::AllCuMask() & ~board->GetEnabledLayers() )[layer] )
-            continue;
+        std::function<bool( wxString* )> textResolver =
+                [&]( wxString* token ) -> bool
+                {
+                    // Handles board->GetTitleBlock() *and* board->GetProject()
+                    return m_editFrame->GetBoard()->ResolveTextVar( token, 0 );
+                };
 
-        // Pick the basename from the board file
-        wxFileName fn( boardFilename );
+        wxString path = m_plotOpts.GetOutputDirectory();
+        path = ExpandTextVars( path, &textResolver );
+        path = ExpandEnvVarSubstitutions( path, board->GetProject() );
 
-        // Use Gerber Extensions based on layer number
-        // (See http://en.wikipedia.org/wiki/Gerber_File)
-        if( m_plotOpts.GetFormat() == PLOT_FORMAT::GERBER && m_useGerberExtensions->GetValue() )
-            file_ext = GetGerberProtelExtension( layer );
+        wxFileName outputDir = wxFileName::DirName( path );
+        wxString   boardFilename = m_editFrame->GetBoard()->GetFileName();
+        REPORTER&  reporter = m_messagesPanel->Reporter();
 
-        BuildPlotFileName( &fn, outputDir.GetPath(), layerName, file_ext );
-        wxString fullname = fn.GetFullName();
-        jobfile_writer.AddGbrFile( layer, fullname );
-
-        LOCALE_IO toggle;
-
-        PLOTTER* plotter = StartPlotBoard( board, &m_plotOpts, layer, layerName, fn.GetFullPath(),
-                                           sheetName, sheetPath );
-
-        // Print diags in messages box:
-        wxString msg;
-
-        if( plotter )
+        if( !EnsureFileDirectoryExists( &outputDir, boardFilename, &reporter ) )
         {
-            plotter->SetTitle( ExpandTextVars( board->GetTitleBlock().GetTitle(), &textResolver ) );
+            wxString msg;
+            msg.Printf( _( "Could not write plot files to folder '%s'." ), outputDir.GetPath() );
+            DisplayError( this, msg );
+            return;
+        }
 
-            if( m_plotOpts.m_PDFMetadata )
+        if( m_zoneFillCheck->GetValue() )
+            m_editFrame->GetToolManager()->GetTool<ZONE_FILLER_TOOL>()->CheckAllZones( this );
+
+        m_plotOpts.SetAutoScale( false );
+
+        switch( m_plotOpts.GetScaleSelection() )
+        {
+        default: m_plotOpts.SetScale( 1 );        break;
+        case 0:  m_plotOpts.SetAutoScale( true ); break;
+        case 2:  m_plotOpts.SetScale( 1.5 );      break;
+        case 3:  m_plotOpts.SetScale( 2 );        break;
+        case 4:  m_plotOpts.SetScale( 3 );        break;
+        }
+
+        /* If the scale factor edit controls are disabled or the scale value
+         * is 0, don't adjust the base scale factor. This fixes a bug when
+         * the default scale adjust is initialized to 0 and saved in program
+         * settings resulting in a divide by zero fault.
+         */
+        if( getPlotFormat() == PLOT_FORMAT::POST )
+        {
+            if( m_XScaleAdjust != 0.0 )
+                m_plotOpts.SetFineScaleAdjustX( m_XScaleAdjust );
+
+            if( m_YScaleAdjust != 0.0 )
+                m_plotOpts.SetFineScaleAdjustY( m_YScaleAdjust );
+
+            m_plotOpts.SetWidthAdjust( m_PSWidthAdjust );
+        }
+
+        wxString file_ext( GetDefaultPlotExtension( m_plotOpts.GetFormat() ) );
+
+        // Test for a reasonable scale value
+        // XXX could this actually happen? isn't it constrained in the apply function?
+        if( m_plotOpts.GetScale() < PLOT_MIN_SCALE )
+            DisplayInfoMessage( this, _( "Warning: Scale option set to a very small value" ) );
+
+        if( m_plotOpts.GetScale() > PLOT_MAX_SCALE )
+            DisplayInfoMessage( this, _( "Warning: Scale option set to a very large value" ) );
+
+        GERBER_JOBFILE_WRITER jobfile_writer( board, &reporter );
+
+        // Save the current plot options in the board
+        m_editFrame->SetPlotSettings( m_plotOpts );
+
+        wxBusyCursor dummy;
+
+        for( PCB_LAYER_ID layer : m_plotOpts.GetLayerSelection().UIOrder() )
+        {
+            LSEQ plotSequence;
+
+            // Base layer always gets plotted first.
+            plotSequence.push_back( layer );
+
+            // Add selected layers from plot on all layers list in order set by user.
+            wxArrayInt plotOnAllLayers;
+
+            if( m_plotAllLayersList->GetCheckedItems( plotOnAllLayers ) )
             {
-                msg = wxS( "AUTHOR" );
+                size_t count = plotOnAllLayers.GetCount();
 
-                if( board->ResolveTextVar( &msg, 0 ) )
-                    plotter->SetAuthor( msg );
+                for( size_t i = 0; i < count; i++ )
+                {
+                    int index = plotOnAllLayers.Item( i );
+                    PCB_LAYER_ID client_layer = getLayerClientData( m_plotAllLayersList, index )->Layer();
 
-                msg = wxS( "SUBJECT" );
+                    // Don't plot the same layer more than once;
+                    if( find( plotSequence.begin(), plotSequence.end(), client_layer ) != plotSequence.end() )
+                        continue;
 
-                if( board->ResolveTextVar( &msg, 0 ) )
-                    plotter->SetSubject( msg );
+                    plotSequence.push_back( client_layer );
+                }
             }
 
-            PlotBoardLayers( board, plotter, plotSequence, m_plotOpts );
-            PlotInteractiveLayer( board, plotter, m_plotOpts );
-            plotter->EndPlot();
-            delete plotter->RenderSettings();
-            delete plotter;
+            wxString     layerName = board->GetLayerName( layer );
+            //@todo allow controlling the sheet name and path that will be displayed in the title block
+            // Leave blank for now
+            wxString     sheetName;
+            wxString     sheetPath;
 
-            msg.Printf( _( "Plotted to '%s'." ), fn.GetFullPath() );
-            reporter.Report( msg, RPT_SEVERITY_ACTION );
+            // All copper layers that are disabled are actually selected
+            // This is due to wonkyness in automatically selecting copper layers
+            // for plotting when adding more than two layers to a board.
+            // If plot options become accessible to the layers setup dialog
+            // please move this functionality there!
+            // This skips a copper layer if it is actually disabled on the board.
+            if( ( LSET::AllCuMask() & ~board->GetEnabledLayers() )[layer] )
+                continue;
+
+            // Pick the basename from the board file
+            wxFileName fn( boardFilename );
+
+            // Use Gerber Extensions based on layer number
+            // (See http://en.wikipedia.org/wiki/Gerber_File)
+            if( m_plotOpts.GetFormat() == PLOT_FORMAT::GERBER && m_useGerberExtensions->GetValue() )
+                file_ext = GetGerberProtelExtension( layer );
+
+            BuildPlotFileName( &fn, outputDir.GetPath(), layerName, file_ext );
+            wxString fullname = fn.GetFullName();
+            jobfile_writer.AddGbrFile( layer, fullname );
+
+            LOCALE_IO toggle;
+
+            PLOTTER* plotter = StartPlotBoard( board, &m_plotOpts, layer, layerName, fn.GetFullPath(),
+                                               sheetName, sheetPath );
+
+            // Print diags in messages box:
+            wxString msg;
+
+            if( plotter )
+            {
+                plotter->SetTitle( ExpandTextVars( board->GetTitleBlock().GetTitle(), &textResolver ) );
+
+                if( m_plotOpts.m_PDFMetadata )
+                {
+                    msg = wxS( "AUTHOR" );
+
+                    if( board->ResolveTextVar( &msg, 0 ) )
+                        plotter->SetAuthor( msg );
+
+                    msg = wxS( "SUBJECT" );
+
+                    if( board->ResolveTextVar( &msg, 0 ) )
+                        plotter->SetSubject( msg );
+                }
+
+                PlotBoardLayers( board, plotter, plotSequence, m_plotOpts );
+                PlotInteractiveLayer( board, plotter, m_plotOpts );
+                plotter->EndPlot();
+                delete plotter->RenderSettings();
+                delete plotter;
+
+                msg.Printf( _( "Plotted to '%s'." ), fn.GetFullPath() );
+                reporter.Report( msg, RPT_SEVERITY_ACTION );
+            }
+            else
+            {
+                msg.Printf( _( "Failed to create file '%s'." ), fn.GetFullPath() );
+                reporter.Report( msg, RPT_SEVERITY_ERROR );
+            }
+
+            wxSafeYield();      // displays report message.
         }
-        else
+
+        if( m_plotOpts.GetFormat() == PLOT_FORMAT::GERBER && m_plotOpts.GetCreateGerberJobFile() )
         {
-            msg.Printf( _( "Failed to create file '%s'." ), fn.GetFullPath() );
-            reporter.Report( msg, RPT_SEVERITY_ERROR );
+            // Pick the basename from the board file
+            wxFileName fn( boardFilename );
+
+            // Build gerber job file from basename
+            BuildPlotFileName( &fn, outputDir.GetPath(), wxT( "job" ),
+                               FILEEXT::GerberJobFileExtension );
+            jobfile_writer.CreateJobFile( fn.GetFullPath() );
         }
 
-        wxSafeYield();      // displays report message.
+        reporter.ReportTail( _( "Done." ), RPT_SEVERITY_INFO );
     }
-
-    if( m_plotOpts.GetFormat() == PLOT_FORMAT::GERBER && m_plotOpts.GetCreateGerberJobFile() )
-    {
-        // Pick the basename from the board file
-        wxFileName fn( boardFilename );
-
-        // Build gerber job file from basename
-        BuildPlotFileName( &fn, outputDir.GetPath(), wxT( "job" ),
-                           FILEEXT::GerberJobFileExtension );
-        jobfile_writer.CreateJobFile( fn.GetFullPath() );
-    }
-
-    reporter.ReportTail( _( "Done." ), RPT_SEVERITY_INFO );
 }
 
 
diff --git a/pcbnew/dialogs/dialog_plot.h b/pcbnew/dialogs/dialog_plot.h
index d527bb776d..73a6fef510 100644
--- a/pcbnew/dialogs/dialog_plot.h
+++ b/pcbnew/dialogs/dialog_plot.h
@@ -32,6 +32,7 @@
 class wxRearrangeList;
 class wxBitmapButton;
 
+class JOB_EXPORT_PCB_PLOT;
 
 /**
  * A dialog to set the plot options and create plot files in various formats.
@@ -39,11 +40,14 @@ class wxBitmapButton;
 class DIALOG_PLOT : public DIALOG_PLOT_BASE
 {
 public:
-    DIALOG_PLOT( PCB_EDIT_FRAME* parent );
+    DIALOG_PLOT( PCB_EDIT_FRAME* aEditFrame );
+    DIALOG_PLOT( PCB_EDIT_FRAME* aEditFrame, wxWindow* aParent,
+                 JOB_EXPORT_PCB_PLOT* aJob = nullptr );
 
     virtual ~DIALOG_PLOT();
 
 private:
+
     // Event called functions
     void Plot( wxCommandEvent& event ) override;
     void OnOutputDirectoryBrowseClicked( wxCommandEvent& event ) override;
@@ -69,6 +73,8 @@ private:
     void applyPlotSettings();
     PLOT_FORMAT getPlotFormat();
 
+    void updateJobFromDialog();
+
     void setPlotModeChoiceSelection( OUTLINE_MODE aPlotMode )
     {
         m_plotModeOpt->SetSelection( aPlotMode == SKETCH ? 1 : 0 );
@@ -77,7 +83,7 @@ private:
     void arrangeAllLayersList( const LSEQ& aSeq );
 
 private:
-    PCB_EDIT_FRAME*     m_parent;
+    PCB_EDIT_FRAME*     m_editFrame;
     LSEQ                m_layerList;                // List to hold CheckListBox layer numbers
     double              m_XScaleAdjust;             // X scale factor adjust to compensate
                                                     // plotter X scaling error
@@ -102,6 +108,8 @@ private:
     STD_BITMAP_BUTTON*  m_bpMoveUp;
     STD_BITMAP_BUTTON*  m_bpMoveDown;
 
+    JOB_EXPORT_PCB_PLOT* m_job;
+
     /// The plot layer set that last time the dialog was opened.
     static LSET         s_lastLayerSet;
     static LSET         s_lastAllLayersSet;
diff --git a/pcbnew/exporters/export_gencad_writer.cpp b/pcbnew/exporters/export_gencad_writer.cpp
index 479d3bf5d9..08abdedd6f 100644
--- a/pcbnew/exporters/export_gencad_writer.cpp
+++ b/pcbnew/exporters/export_gencad_writer.cpp
@@ -153,7 +153,7 @@ double GENCAD_EXPORTER::MapYTo( int aY )
 }
 
 
-bool GENCAD_EXPORTER::WriteFile( wxString& aFullFileName )
+bool GENCAD_EXPORTER::WriteFile( const wxString& aFullFileName )
 {
     componentShapes.clear();
     shapeNames.clear();
diff --git a/pcbnew/exporters/export_gencad_writer.h b/pcbnew/exporters/export_gencad_writer.h
index 9f8c47dd4a..e104cedfb2 100644
--- a/pcbnew/exporters/export_gencad_writer.h
+++ b/pcbnew/exporters/export_gencad_writer.h
@@ -39,7 +39,7 @@ public:
      * @param aFullFileName is the full filenam to create
      * @return true on success
      */
-    bool WriteFile( wxString& aFullFileName );
+    bool WriteFile( const wxString& aFullFileName );
 
     /// Set the coordinates offet when exporting items
     void SetPlotOffet( VECTOR2I aOffset ) { GencadOffset = aOffset; }
diff --git a/pcbnew/exporters/gerber_placefile_writer.cpp b/pcbnew/exporters/gerber_placefile_writer.cpp
index e3c472f2ee..bd4e02e3f8 100644
--- a/pcbnew/exporters/gerber_placefile_writer.cpp
+++ b/pcbnew/exporters/gerber_placefile_writer.cpp
@@ -48,7 +48,7 @@ PLACEFILE_GERBER_WRITER::PLACEFILE_GERBER_WRITER( BOARD* aPcb )
 }
 
 
-int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, PCB_LAYER_ID aLayer,
+int PLACEFILE_GERBER_WRITER::CreatePlaceFile( const wxString& aFullFilename, PCB_LAYER_ID aLayer,
                                               bool aIncludeBrdEdges )
 {
     m_layer = aLayer;
diff --git a/pcbnew/exporters/gerber_placefile_writer.h b/pcbnew/exporters/gerber_placefile_writer.h
index c72ef9675b..7356305fda 100644
--- a/pcbnew/exporters/gerber_placefile_writer.h
+++ b/pcbnew/exporters/gerber_placefile_writer.h
@@ -66,7 +66,7 @@ public:
      * @param aIncludeBrdEdges use true to include board outlines.
      * @return component count, or -1 if the file cannot be created.
      */
-    int CreatePlaceFile( wxString& aFullFilename, PCB_LAYER_ID aLayer, bool aIncludeBrdEdges );
+    int CreatePlaceFile( const wxString& aFullFilename, PCB_LAYER_ID aLayer, bool aIncludeBrdEdges );
 
     /**
      * @param aFullBaseFilename = a full filename. it will be modified
diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp
index 548dfc5e57..50b91049ce 100644
--- a/pcbnew/pcbnew.cpp
+++ b/pcbnew/pcbnew.cpp
@@ -338,6 +338,8 @@ static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER
 
     int HandleJob( JOB* aJob ) override;
 
+    bool HandleJobConfig( JOB* aJob, wxWindow* aParent ) override;
+
 private:
     bool loadGlobalLibTable();
 
@@ -573,3 +575,9 @@ int IFACE::HandleJob( JOB* aJob )
 {
     return m_jobHandler->RunJob( aJob );
 }
+
+
+bool IFACE::HandleJobConfig( JOB* aJob, wxWindow* aParent )
+{
+    return m_jobHandler->HandleJobConfig( aJob, aParent );
+}
diff --git a/pcbnew/pcbnew_jobs_handler.cpp b/pcbnew/pcbnew_jobs_handler.cpp
index 1fb4bf23ec..03b422169d 100644
--- a/pcbnew/pcbnew_jobs_handler.cpp
+++ b/pcbnew/pcbnew_jobs_handler.cpp
@@ -76,6 +76,13 @@
 #include <export_vrml.h>
 #include <wx/wfstream.h>
 #include <wx/zipstrm.h>
+#include <settings/settings_manager.h>
+#include <dialogs/dialog_export_svg.h>
+#include <dialogs/dialog_gendrill.h>
+#include <dialogs/dialog_gen_footprint_position.h>
+#include <dialogs/dialog_export_2581.h>
+#include <dialogs/dialog_export_step.h>
+#include <dialogs/dialog_plot.h>
 
 #include "pcbnew_scripting_helpers.h"
 
@@ -88,29 +95,191 @@
 
 
 PCBNEW_JOBS_HANDLER::PCBNEW_JOBS_HANDLER( KIWAY* aKiway ) :
-        JOB_DISPATCHER( aKiway )
+        JOB_DISPATCHER( aKiway ),
+        m_cliBoard( nullptr )
 {
-    Register( "3d", std::bind( &PCBNEW_JOBS_HANDLER::JobExportStep, this, std::placeholders::_1 ) );
-    Register( "render", std::bind( &PCBNEW_JOBS_HANDLER::JobExportRender, this, std::placeholders::_1 ) );
-    Register( "svg", std::bind( &PCBNEW_JOBS_HANDLER::JobExportSvg, this, std::placeholders::_1 ) );
+    Register( "3d", std::bind( &PCBNEW_JOBS_HANDLER::JobExportStep, this, std::placeholders::_1 ),
+              [aKiway]( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  JOB_EXPORT_PCB_3D* svgJob = dynamic_cast<JOB_EXPORT_PCB_3D*>( job );
+
+                  PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
+                          aKiway->Player( FRAME_PCB_EDITOR, false ) );
+                  DIALOG_EXPORT_STEP dlg( editFrame, aParent, "", svgJob );
+                  dlg.ShowModal();
+
+                  return dlg.GetReturnCode() == wxID_OK;
+              } );
+    Register( "render",
+              std::bind( &PCBNEW_JOBS_HANDLER::JobExportRender, this, std::placeholders::_1 ),
+              []( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  return false;
+              } );
+    Register( "svg", std::bind( &PCBNEW_JOBS_HANDLER::JobExportSvg, this, std::placeholders::_1 ),
+              [aKiway]( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  JOB_EXPORT_PCB_SVG* svgJob = dynamic_cast<JOB_EXPORT_PCB_SVG*>( job );
+
+                  PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
+                          aKiway->Player( FRAME_PCB_EDITOR, false ) );
+                  DIALOG_EXPORT_SVG dlg( svgJob, editFrame, aParent );
+                  dlg.ShowModal();
+
+                  return dlg.GetReturnCode() == wxID_OK;
+              } );
     Register( "gencad",
-              std::bind( &PCBNEW_JOBS_HANDLER::JobExportGencad, this, std::placeholders::_1 ) );
-    Register( "dxf", std::bind( &PCBNEW_JOBS_HANDLER::JobExportDxf, this, std::placeholders::_1 ) );
-    Register( "pdf", std::bind( &PCBNEW_JOBS_HANDLER::JobExportPdf, this, std::placeholders::_1 ) );
+              std::bind( &PCBNEW_JOBS_HANDLER::JobExportGencad, this, std::placeholders::_1 ),
+              []( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  return false;
+              } );
+    Register( "dxf", std::bind( &PCBNEW_JOBS_HANDLER::JobExportDxf, this, std::placeholders::_1 ),
+              [aKiway]( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  JOB_EXPORT_PCB_DXF* dxfJob = dynamic_cast<JOB_EXPORT_PCB_DXF*>( job );
+
+                  PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
+                          aKiway->Player( FRAME_PCB_EDITOR, false ) );
+
+                  DIALOG_PLOT dlg( editFrame, aParent, dxfJob );
+                  dlg.ShowModal();
+
+                  return dlg.GetReturnCode() == wxID_OK;
+              } );
+    Register( "pdf", std::bind( &PCBNEW_JOBS_HANDLER::JobExportPdf, this, std::placeholders::_1 ),
+              [aKiway]( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  JOB_EXPORT_PCB_PDF* pdfJob = dynamic_cast<JOB_EXPORT_PCB_PDF*>( job );
+
+                  PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
+                          aKiway->Player( FRAME_PCB_EDITOR, false ) );
+
+                  DIALOG_PLOT dlg( editFrame, aParent, pdfJob );
+                  dlg.ShowModal();
+
+                  return dlg.GetReturnCode() == wxID_OK;
+              } );
     Register( "gerber",
-              std::bind( &PCBNEW_JOBS_HANDLER::JobExportGerber, this, std::placeholders::_1 ) );
+              std::bind( &PCBNEW_JOBS_HANDLER::JobExportGerber, this, std::placeholders::_1 ),
+              [aKiway]( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  JOB_EXPORT_PCB_GERBER* gJob = dynamic_cast<JOB_EXPORT_PCB_GERBER*>( job );
+
+                  PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
+                          aKiway->Player( FRAME_PCB_EDITOR, false ) );
+
+                  DIALOG_PLOT dlg( editFrame, aParent, gJob );
+                  dlg.ShowModal();
+
+                  return dlg.GetReturnCode() == wxID_OK;
+              } );
     Register( "gerbers",
-              std::bind( &PCBNEW_JOBS_HANDLER::JobExportGerbers, this, std::placeholders::_1 ) );
+              std::bind( &PCBNEW_JOBS_HANDLER::JobExportGerbers, this, std::placeholders::_1 ),
+              [aKiway]( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  JOB_EXPORT_PCB_GERBERS* gJob = dynamic_cast<JOB_EXPORT_PCB_GERBERS*>( job );
+
+                  PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>(
+                          aKiway->Player( FRAME_PCB_EDITOR, false ) );
+
+                  DIALOG_PLOT dlg( editFrame, aParent, gJob );
+                  dlg.ShowModal();
+
+                  return dlg.GetReturnCode() == wxID_OK;
+              } );
     Register( "drill",
-              std::bind( &PCBNEW_JOBS_HANDLER::JobExportDrill, this, std::placeholders::_1 ) );
-    Register( "pos", std::bind( &PCBNEW_JOBS_HANDLER::JobExportPos, this, std::placeholders::_1 ) );
+              std::bind( &PCBNEW_JOBS_HANDLER::JobExportDrill, this, std::placeholders::_1 ),
+              [aKiway]( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  JOB_EXPORT_PCB_DRILL* drillJob = dynamic_cast<JOB_EXPORT_PCB_DRILL*>( job );
+
+                  PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( aKiway->Player( FRAME_PCB_EDITOR, false ) );
+                  DIALOG_GENDRILL dlg( editFrame, drillJob, aParent );
+                  dlg.ShowModal();
+                  return dlg.GetReturnCode() == wxID_OK;
+              } );
+    Register( "pos", std::bind( &PCBNEW_JOBS_HANDLER::JobExportPos, this, std::placeholders::_1 ),
+              [aKiway]( JOB* job, wxWindow* aParent ) -> bool
+			  {
+				  JOB_EXPORT_PCB_POS* posJob = dynamic_cast<JOB_EXPORT_PCB_POS*>( job );
+
+				  PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( aKiway->Player( FRAME_PCB_EDITOR, false ) );
+				  DIALOG_GEN_FOOTPRINT_POSITION dlg( posJob, editFrame, aParent );
+                  dlg.ShowModal();
+                  return dlg.GetReturnCode() == wxID_OK;
+			  } );
     Register( "fpupgrade",
-              std::bind( &PCBNEW_JOBS_HANDLER::JobExportFpUpgrade, this, std::placeholders::_1 ) );
+              std::bind( &PCBNEW_JOBS_HANDLER::JobExportFpUpgrade, this, std::placeholders::_1 ),
+              []( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  return false;
+              } );
     Register( "fpsvg",
-              std::bind( &PCBNEW_JOBS_HANDLER::JobExportFpSvg, this, std::placeholders::_1 ) );
-    Register( "drc", std::bind( &PCBNEW_JOBS_HANDLER::JobExportDrc, this, std::placeholders::_1 ) );
+              std::bind( &PCBNEW_JOBS_HANDLER::JobExportFpSvg, this, std::placeholders::_1 ),
+              []( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  return false;
+              } );
+    Register( "drc", std::bind( &PCBNEW_JOBS_HANDLER::JobExportDrc, this, std::placeholders::_1 ),
+              []( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  return false;
+              } );
     Register( "ipc2581",
-              std::bind( &PCBNEW_JOBS_HANDLER::JobExportIpc2581, this, std::placeholders::_1 ) );
+              std::bind( &PCBNEW_JOBS_HANDLER::JobExportIpc2581, this, std::placeholders::_1 ),
+              [aKiway]( JOB* job, wxWindow* aParent ) -> bool
+              {
+                  JOB_EXPORT_PCB_IPC2581* ipcJob = dynamic_cast<JOB_EXPORT_PCB_IPC2581*>( job );
+
+                  PCB_EDIT_FRAME* editFrame = dynamic_cast<PCB_EDIT_FRAME*>( aKiway->Player( FRAME_PCB_EDITOR, false ) );
+
+                  DIALOG_EXPORT_2581 dlg( ipcJob, editFrame, aParent );
+                  dlg.ShowModal();
+
+                  return dlg.GetReturnCode() == wxID_OK;
+              } );
+}
+
+
+BOARD* PCBNEW_JOBS_HANDLER::getBoard( const wxString& aPath )
+{
+    BOARD* brd = nullptr;
+
+    if( !Pgm().IsGUI() &&
+        Pgm().GetSettingsManager().IsProjectOpen() )
+    {
+        PROJECT& project = Pgm().GetSettingsManager().Prj();
+
+        wxString pcbPath = aPath;
+        if( pcbPath.IsEmpty() )
+        {
+            wxFileName path = project.GetProjectFullName();
+            path.SetExt( FILEEXT::KiCadPcbFileExtension );
+            path.MakeAbsolute();
+            pcbPath = path.GetFullPath();
+        }
+
+        if( !m_cliBoard )
+        {
+            m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
+            m_cliBoard = LoadBoard( pcbPath, true, &project );
+        }
+
+        brd = m_cliBoard;
+    }
+    else
+    {
+        m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
+        brd = LoadBoard( aPath, true, &Pgm().GetSettingsManager().Prj() );
+    }
+
+    if ( !brd )
+    {
+        m_reporter->Report( _( "Failed to load board\n" ), RPT_SEVERITY_ERROR );
+    }
+
+    return brd;
 }
 
 
@@ -121,14 +290,15 @@ int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob )
     if( aStepJob == nullptr )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
 
-    if( aJob->IsCli() )
-        m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
+    BOARD* brd = getBoard( aStepJob->m_filename );
+
+    if( !brd )
+        return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
 
-    BOARD* brd = LoadBoard( aStepJob->m_filename, true );
     brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
     brd->SynchronizeProperties();
 
-    if( aStepJob->m_3dparams.m_OutputFile.IsEmpty() )
+    if( aStepJob->GetOutputPath().IsEmpty() )
     {
         wxFileName fn = brd->GetFileName();
         fn.SetName( fn.GetName() );
@@ -149,7 +319,7 @@ int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob )
             return CLI::EXIT_CODES::ERR_UNKNOWN; // shouldnt have gotten here
         }
 
-        aStepJob->m_3dparams.m_OutputFile = fn.GetFullName();
+        aStepJob->SetOutputPath( fn.GetFullName() );
     }
 
     if( aStepJob->m_format == JOB_EXPORT_PCB_3D::FORMAT::VRML )
@@ -178,7 +348,7 @@ int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob )
         }
 
         bool success = vrmlExporter.ExportVRML_File(
-                brd->GetProject(), &messages, aStepJob->m_3dparams.m_OutputFile, scale,
+                brd->GetProject(), &messages, aStepJob->GetFullOutputPath(), scale,
                 aStepJob->m_3dparams.m_IncludeUnspecified, aStepJob->m_3dparams.m_IncludeDNP,
                 !aStepJob->m_vrmlModelDir.IsEmpty(), aStepJob->m_vrmlRelativePaths,
                 aStepJob->m_vrmlModelDir, originX, originY );
@@ -186,7 +356,7 @@ int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob )
         if ( success )
         {
             m_reporter->Report( wxString::Format( _( "Successfully exported VRML to %s" ),
-                                                  aStepJob->m_3dparams.m_OutputFile ),
+                                                  aStepJob->GetFullOutputPath() ),
                                 RPT_SEVERITY_INFO );
         }
         else
@@ -218,7 +388,7 @@ int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob )
         }
 
         EXPORTER_STEP stepExporter( brd, params );
-        stepExporter.m_outputFile = params.m_OutputFile;
+        stepExporter.m_outputFile = aStepJob->GetFullOutputPath();
 
         if( !stepExporter.Export() )
             return CLI::EXIT_CODES::ERR_UNKNOWN;
@@ -235,10 +405,11 @@ int PCBNEW_JOBS_HANDLER::JobExportRender( JOB* aJob )
     if( aRenderJob == nullptr )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
 
-    if( aJob->IsCli() )
-        m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
+    BOARD* brd = getBoard( aRenderJob->m_filename );
+
+    if( !brd )
+        return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
 
-    BOARD* brd = LoadBoard( aRenderJob->m_filename, true );
     brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
     brd->SynchronizeProperties();
 
@@ -419,7 +590,7 @@ int PCBNEW_JOBS_HANDLER::JobExportSvg( JOB* aJob )
     PCB_PLOT_SVG_OPTIONS svgPlotOptions;
     svgPlotOptions.m_blackAndWhite = aSvgJob->m_blackAndWhite;
     svgPlotOptions.m_colorTheme = aSvgJob->m_colorTheme;
-    svgPlotOptions.m_outputFile = aSvgJob->m_outputFile;
+    svgPlotOptions.m_outputFile = aSvgJob->GetFullOutputPath();
     svgPlotOptions.m_mirror = aSvgJob->m_mirror;
     svgPlotOptions.m_negative = aSvgJob->m_negative;
     svgPlotOptions.m_pageSizeMode = aSvgJob->m_pageSizeMode;
@@ -431,10 +602,11 @@ int PCBNEW_JOBS_HANDLER::JobExportSvg( JOB* aJob )
     svgPlotOptions.m_crossoutDNPFPsOnFabLayers = aSvgJob->m_crossoutDNPFPsOnFabLayers;
     svgPlotOptions.m_drillShapeOption = aSvgJob->m_drillShapeOption;
 
-    if( aJob->IsCli() )
-        m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
+    BOARD* brd = getBoard( aSvgJob->m_filename );
+
+    if( !brd )
+        return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
 
-    BOARD* brd = LoadBoard( aSvgJob->m_filename, true );
     loadOverrideDrawingSheet( brd, aSvgJob->m_drawingSheet );
     brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
     brd->SynchronizeProperties();
@@ -458,21 +630,22 @@ int PCBNEW_JOBS_HANDLER::JobExportDxf( JOB* aJob )
     if( aDxfJob == nullptr )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
 
-    if( aJob->IsCli() )
-        m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
+    BOARD* brd = getBoard( aDxfJob->m_filename );
+
+    if( !brd )
+        return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
 
-    BOARD* brd = LoadBoard( aDxfJob->m_filename, true );
     loadOverrideDrawingSheet( brd, aDxfJob->m_drawingSheet );
     brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
     brd->SynchronizeProperties();
 
-    if( aDxfJob->m_outputFile.IsEmpty() )
+    if( aDxfJob->GetOutputPath().IsEmpty() )
     {
         wxFileName fn = brd->GetFileName();
         fn.SetName( fn.GetName() );
         fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::DXF ) );
 
-        aDxfJob->m_outputFile = fn.GetFullName();
+        aDxfJob->SetOutputPath( fn.GetFullName() );
     }
 
     PCB_PLOT_PARAMS plotOpts;
@@ -486,7 +659,7 @@ int PCBNEW_JOBS_HANDLER::JobExportDxf( JOB* aJob )
     else
         plotOpts.SetDXFPlotUnits( DXF_UNITS::INCHES );
 
-    plotOpts.SetPlotFrameRef( aDxfJob->m_plotBorderTitleBlocks );
+    plotOpts.SetPlotFrameRef( aDxfJob->m_plotDrawingSheet );
     plotOpts.SetPlotValue( aDxfJob->m_plotFootprintValues );
     plotOpts.SetPlotReference( aDxfJob->m_plotRefDes );
     plotOpts.SetLayerSelection( aDxfJob->m_printMaskLayer );
@@ -511,8 +684,7 @@ int PCBNEW_JOBS_HANDLER::JobExportDxf( JOB* aJob )
     if( aJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
         sheetPath = aJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
 
-    DXF_PLOTTER* plotter = (DXF_PLOTTER*) StartPlotBoard( brd, &plotOpts, layer, layerName,
-                                                          aDxfJob->m_outputFile, sheetName,
+    DXF_PLOTTER* plotter = (DXF_PLOTTER*) StartPlotBoard( brd, &plotOpts, layer, layerName, aDxfJob->GetFullOutputPath(), sheetName,
                                                           sheetPath );
 
     if( plotter )
@@ -534,27 +706,28 @@ int PCBNEW_JOBS_HANDLER::JobExportPdf( JOB* aJob )
     if( aPdfJob == nullptr )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
 
-    if( aJob->IsCli() )
-        m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
+    BOARD* brd = getBoard( aPdfJob->m_filename );
+
+    if( !brd )
+        return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
 
-    BOARD* brd = LoadBoard( aPdfJob->m_filename, true );
     loadOverrideDrawingSheet( brd, aPdfJob->m_drawingSheet );
     brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
     brd->SynchronizeProperties();
 
-    if( aPdfJob->m_outputFile.IsEmpty() )
+    if( aPdfJob->OutputPathFullSpecified() )
     {
         wxFileName fn = brd->GetFileName();
         fn.SetName( fn.GetName() );
         fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::PDF ) );
 
-        aPdfJob->m_outputFile = fn.GetFullName();
+        aPdfJob->SetOutputPath( fn.GetFullName() );
     }
 
     PCB_PLOT_PARAMS plotOpts;
     plotOpts.SetFormat( PLOT_FORMAT::PDF );
 
-    plotOpts.SetPlotFrameRef( aPdfJob->m_plotBorderTitleBlocks );
+    plotOpts.SetPlotFrameRef( aPdfJob->m_plotDrawingSheet );
     plotOpts.SetPlotValue( aPdfJob->m_plotFootprintValues );
     plotOpts.SetPlotReference( aPdfJob->m_plotRefDes );
 
@@ -604,8 +777,7 @@ int PCBNEW_JOBS_HANDLER::JobExportPdf( JOB* aJob )
     if( aPdfJob->GetVarOverrides().contains( wxT( "SHEETPATH" ) ) )
         sheetPath = aPdfJob->GetVarOverrides().at( wxT( "SHEETPATH" ) );
 
-    PDF_PLOTTER* plotter = (PDF_PLOTTER*) StartPlotBoard( brd, &plotOpts, layer, layerName,
-                                                          aPdfJob->m_outputFile, sheetName,
+    PDF_PLOTTER* plotter = (PDF_PLOTTER*) StartPlotBoard( brd, &plotOpts, layer, layerName, aPdfJob->GetFullOutputPath(), sheetName,
                                                           sheetPath );
 
     if( plotter )
@@ -629,10 +801,11 @@ int PCBNEW_JOBS_HANDLER::JobExportGerbers( JOB* aJob )
     if( aGerberJob == nullptr )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
 
-    if( aJob->IsCli() )
-        m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
+    BOARD* brd = getBoard( aGerberJob->m_filename );
+
+    if( !brd )
+        return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
 
-    BOARD* brd = LoadBoard( aGerberJob->m_filename, true );
     loadOverrideDrawingSheet( brd, aGerberJob->m_drawingSheet );
     brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
     brd->SynchronizeProperties();
@@ -701,7 +874,7 @@ int PCBNEW_JOBS_HANDLER::JobExportGerbers( JOB* aJob )
         else
             fileExt = FILEEXT::GerberFileExtension;
 
-        BuildPlotFileName( &fn, aGerberJob->m_outputFile, layerName, fileExt );
+        BuildPlotFileName( &fn, aGerberJob->GetFullOutputPath(), layerName, fileExt );
         wxString fullname = fn.GetFullName();
 
         jobfile_writer.AddGbrFile( layer, fullname );
@@ -741,7 +914,7 @@ int PCBNEW_JOBS_HANDLER::JobExportGerbers( JOB* aJob )
     wxFileName fn( aGerberJob->m_filename );
 
     // Build gerber job file from basename
-    BuildPlotFileName( &fn, aGerberJob->m_outputFile, wxT( "job" ),
+    BuildPlotFileName( &fn, aGerberJob->GetFullOutputPath(), wxT( "job" ),
                        FILEEXT::GerberJobFileExtension );
     jobfile_writer.CreateJobFile( fn.GetFullPath() );
 
@@ -773,23 +946,19 @@ int PCBNEW_JOBS_HANDLER::JobExportGencad( JOB* aJob )
     exporter.SetPlotOffet( GencadOffset );
     exporter.StoreOriginCoordsInFile( aGencadJob->m_storeOriginCoords );
 
-    m_reporter->Report( aGencadJob->m_outputFile, RPT_SEVERITY_ERROR );
-
-    wxString outputFile = aGencadJob->m_outputFile;
-
-    if( outputFile.IsEmpty() )
+    if( aGencadJob->GetOutputPath().IsEmpty() )
     {
         wxFileName fn = aBoard->GetFileName();
         fn.SetName( fn.GetName() );
-        fn.SetExt( wxS( "cad" ) );
+        fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::DXF ) );
 
-        outputFile = fn.GetFullName();
+        aGencadJob->SetOutputPath( fn.GetFullName() );
     }
 
-    if( !exporter.WriteFile( outputFile ) )
+    if( !exporter.WriteFile( aGencadJob->GetFullOutputPath() ) )
     {
         wxString msg;
-        msg.Printf( _( "Failed to create file '%s'.\n" ), outputFile );
+        msg.Printf( _( "Failed to create file '%s'.\n" ), aGencadJob->GetFullOutputPath() );
 
         if( aJob->IsCli() )
             m_reporter->Report( msg, RPT_SEVERITY_ERROR );
@@ -809,7 +978,7 @@ void PCBNEW_JOBS_HANDLER::populateGerberPlotOptionsFromJob( PCB_PLOT_PARAMS& aPl
 {
     aPlotOpts.SetFormat( PLOT_FORMAT::GERBER );
 
-    aPlotOpts.SetPlotFrameRef( aJob->m_plotBorderTitleBlocks );
+    aPlotOpts.SetPlotFrameRef( aJob->m_plotDrawingSheet );
     aPlotOpts.SetPlotValue( aJob->m_plotFootprintValues );
     aPlotOpts.SetPlotReference( aJob->m_plotRefDes );
 
@@ -835,20 +1004,21 @@ int PCBNEW_JOBS_HANDLER::JobExportGerber( JOB* aJob )
     if( aGerberJob == nullptr )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
 
-    if( aJob->IsCli() )
-        m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
+    BOARD* brd = getBoard( aGerberJob->m_filename );
+
+    if( !brd )
+        return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
 
-    BOARD* brd = LoadBoard( aGerberJob->m_filename, true );
     brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
     brd->SynchronizeProperties();
 
-    if( aGerberJob->m_outputFile.IsEmpty() )
+    if( aGerberJob->GetOutputPath().IsEmpty() )
     {
         wxFileName fn = brd->GetFileName();
         fn.SetName( fn.GetName() );
         fn.SetExt( GetDefaultPlotExtension( PLOT_FORMAT::GERBER ) );
 
-        aGerberJob->m_outputFile = fn.GetFullName();
+        aGerberJob->SetOutputPath( fn.GetFullName() );
     }
 
     PCB_PLOT_PARAMS plotOpts;
@@ -877,7 +1047,7 @@ int PCBNEW_JOBS_HANDLER::JobExportGerber( JOB* aJob )
 
     // We are feeding it one layer at the start here to silence a logic check
     GERBER_PLOTTER* plotter = (GERBER_PLOTTER*) StartPlotBoard( brd, &plotOpts, layer, layerName,
-                                                                aGerberJob->m_outputFile,
+                                                                aGerberJob->GetFullOutputPath(),
                                                                 sheetName, sheetPath );
 
     if( plotter )
@@ -888,7 +1058,7 @@ int PCBNEW_JOBS_HANDLER::JobExportGerber( JOB* aJob )
     else
     {
         m_reporter->Report( wxString::Format( _( "Failed to plot to '%s'.\n" ),
-                                              aGerberJob->m_outputFile ),
+                                              aGerberJob->GetFullOutputPath() ),
                 RPT_SEVERITY_ERROR );
         exitCode = CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
     }
@@ -909,13 +1079,13 @@ int PCBNEW_JOBS_HANDLER::JobExportDrill( JOB* aJob )
     if( aDrillJob == nullptr )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
 
-    if( aJob->IsCli() )
-        m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
+    BOARD* brd = getBoard( aDrillJob->m_filename );
 
-    BOARD* brd = LoadBoard( aDrillJob->m_filename, true );
+    if( !brd )
+        return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
 
     // ensure output dir exists
-    wxFileName fn( aDrillJob->m_outputDir + wxT( "/" ) );
+    wxFileName fn( aDrillJob->GetFullOutputPath() + wxT( "/" ) );
 
     if( !fn.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
     {
@@ -990,7 +1160,7 @@ int PCBNEW_JOBS_HANDLER::JobExportDrill( JOB* aJob )
         excellonWriter->SetRouteModeForOvalHoles( aDrillJob->m_excellonOvalDrillRoute );
         excellonWriter->SetMapFileFormat( mapFormat );
 
-        if( !excellonWriter->CreateDrillandMapFilesSet( aDrillJob->m_outputDir, true,
+        if( !excellonWriter->CreateDrillandMapFilesSet( aDrillJob->GetFullOutputPath(), true,
                                                         aDrillJob->m_generateMap, m_reporter ) )
         {
             return CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
@@ -1010,7 +1180,7 @@ int PCBNEW_JOBS_HANDLER::JobExportDrill( JOB* aJob )
         gerberWriter->SetOptions( offset );
         gerberWriter->SetMapFileFormat( mapFormat );
 
-        if( !gerberWriter->CreateDrillandMapFilesSet( aDrillJob->m_outputDir, true,
+        if( !gerberWriter->CreateDrillandMapFilesSet( aDrillJob->GetFullOutputPath(), true,
                                                       aDrillJob->m_generateMap, m_reporter ) )
         {
             return CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
@@ -1028,12 +1198,14 @@ int PCBNEW_JOBS_HANDLER::JobExportPos( JOB* aJob )
     if( aPosJob == nullptr )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
 
-    if( aJob->IsCli() )
-        m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
+    BOARD* brd = getBoard( aPosJob->m_filename );
 
-    BOARD* brd = LoadBoard( aPosJob->m_filename, true );
+    if( !brd )
+    {
+        return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
+    }
 
-    if( aPosJob->m_outputFile.IsEmpty() )
+    if( aPosJob->GetOutputPath().IsEmpty() )
     {
         wxFileName fn = brd->GetFileName();
         fn.SetName( fn.GetName() );
@@ -1045,14 +1217,14 @@ int PCBNEW_JOBS_HANDLER::JobExportPos( JOB* aJob )
         else if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::GERBER )
             fn.SetExt( FILEEXT::GerberFileExtension );
 
-        aPosJob->m_outputFile = fn.GetFullName();
+        aPosJob->SetOutputPath( fn.GetFullName() );
     }
 
     if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::ASCII
         || aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::CSV )
     {
         FILE* file = nullptr;
-        file = wxFopen( aPosJob->m_outputFile, wxS( "wt" ) );
+        file = wxFopen( aPosJob->GetFullOutputPath(), wxS( "wt" ) );
 
         if( file == nullptr )
             return CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
@@ -1077,6 +1249,8 @@ int PCBNEW_JOBS_HANDLER::JobExportPos( JOB* aJob )
 
         fputs( data.c_str(), file );
         fclose( file );
+
+        aPosJob->AddOutput( aPosJob->GetFullOutputPath() );
     }
     else if( aPosJob->m_format == JOB_EXPORT_PCB_POS::FORMAT::GERBER )
     {
@@ -1087,7 +1261,15 @@ int PCBNEW_JOBS_HANDLER::JobExportPos( JOB* aJob )
         if( aPosJob->m_side == JOB_EXPORT_PCB_POS::SIDE::BACK )
             gbrLayer = B_Cu;
 
-        exporter.CreatePlaceFile( aPosJob->m_outputFile, gbrLayer, aPosJob->m_gerberBoardEdge );
+        if( exporter.CreatePlaceFile( aPosJob->GetFullOutputPath(), gbrLayer, aPosJob->m_gerberBoardEdge )
+            >= 0 )
+        {
+            aPosJob->AddOutput( aPosJob->GetFullOutputPath() );
+        }
+        else
+        {
+            return CLI::EXIT_CODES::ERR_INVALID_OUTPUT_CONFLICT;
+        }
     }
 
     return CLI::EXIT_CODES::OK;
@@ -1332,10 +1514,11 @@ int PCBNEW_JOBS_HANDLER::JobExportDrc( JOB* aJob )
     if( drcJob == nullptr )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
 
-    if( aJob->IsCli() )
-        m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
+    BOARD* brd = getBoard( drcJob->m_filename );
+
+    if( !brd )
+        return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
 
-    BOARD* brd = LoadBoard( drcJob->m_filename, true );
     brd->GetProject()->ApplyTextVars( aJob->GetVarOverrides() );
     brd->SynchronizeProperties();
 
@@ -1500,18 +1683,18 @@ int PCBNEW_JOBS_HANDLER::JobExportIpc2581( JOB* aJob )
     if( job == nullptr )
         return CLI::EXIT_CODES::ERR_UNKNOWN;
 
-    if( job->IsCli() )
-        m_reporter->Report( _( "Loading board\n" ), RPT_SEVERITY_INFO );
+    BOARD* brd = getBoard( job->m_filename );
 
-    BOARD* brd = LoadBoard( job->m_filename, true );
+    if( !brd )
+        return CLI::EXIT_CODES::ERR_INVALID_INPUT_FILE;
 
-    if( job->m_outputFile.IsEmpty() )
+    if( job->OutputPathFullSpecified() )
     {
         wxFileName fn = brd->GetFileName();
         fn.SetName( fn.GetName() );
         fn.SetExt( FILEEXT::Ipc2581FileExtension );
 
-        job->m_outputFile = fn.GetFullName();
+        job->SetOutputPath( fn.GetName() );
     }
 
     std::map<std::string, UTF8> props;
@@ -1545,7 +1728,7 @@ int PCBNEW_JOBS_HANDLER::JobExportIpc2581( JOB* aJob )
 
     if( job->m_compress )
     {
-        wxFileName tempfn = job->m_outputFile;
+        wxFileName tempfn = job->GetFullOutputPath();
         tempfn.SetExt( FILEEXT::Ipc2581FileExtension );
         wxFileName zipfn = tempFile;
         zipfn.SetExt( "zip" );
@@ -1564,12 +1747,12 @@ int PCBNEW_JOBS_HANDLER::JobExportIpc2581( JOB* aJob )
     }
 
     // If save succeeded, replace the original with what we just wrote
-    if( !wxRenameFile( tempFile, job->m_outputFile ) )
+    if( !wxRenameFile( tempFile, job->GetFullOutputPath() ) )
     {
         m_reporter->Report( wxString::Format( _( "Error generating IPC2581 file '%s'.\n"
                                                  "Failed to rename temporary file '%s." )
                                                       + wxS( "\n" ),
-                                              job->m_outputFile, tempFile ),
+                                              job->GetFullOutputPath(), tempFile ),
                             RPT_SEVERITY_ERROR );
     }
 
diff --git a/pcbnew/pcbnew_jobs_handler.h b/pcbnew/pcbnew_jobs_handler.h
index 7d1bfa2a0b..31b4773515 100644
--- a/pcbnew/pcbnew_jobs_handler.h
+++ b/pcbnew/pcbnew_jobs_handler.h
@@ -51,12 +51,15 @@ public:
     int JobExportIpc2581( JOB* aJob );
 
 private:
+    BOARD* getBoard( const wxString& aPath = wxEmptyString );
     void populateGerberPlotOptionsFromJob( PCB_PLOT_PARAMS&       aPlotOpts,
                                            JOB_EXPORT_PCB_GERBER* aJob );
     int  doFpExportSvg( JOB_FP_EXPORT_SVG* aSvgJob, const FOOTPRINT* aFootprint );
     void loadOverrideDrawingSheet( BOARD* brd, const wxString& aSheetPath );
 
     DS_PROXY_VIEW_ITEM* getDrawingSheetProxyView( BOARD* aBrd );
+
+    BOARD* m_cliBoard;
 };
 
 #endif
\ No newline at end of file
diff --git a/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp b/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp
index 221f7a307f..e712e4d9fa 100644
--- a/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp
+++ b/pcbnew/python/scripting/pcbnew_scripting_helpers.cpp
@@ -87,19 +87,19 @@ void ScriptingOnDestructPcbEditFrame( PCB_EDIT_FRAME* aPcbEditFrame )
 }
 
 
-BOARD* LoadBoard( wxString& aFileName, bool aSetActive )
+BOARD* LoadBoard( const wxString& aFileName, bool aSetActive, PROJECT* aProject )
 {
     if( aFileName.EndsWith( FILEEXT::KiCadPcbFileExtension ) )
-        return LoadBoard( aFileName, PCB_IO_MGR::KICAD_SEXP, aSetActive );
+        return LoadBoard( aFileName, PCB_IO_MGR::KICAD_SEXP, aSetActive, aProject );
     else if( aFileName.EndsWith( FILEEXT::LegacyPcbFileExtension ) )
-        return LoadBoard( aFileName, PCB_IO_MGR::LEGACY, aSetActive );
+        return LoadBoard( aFileName, PCB_IO_MGR::LEGACY, aSetActive, aProject );
 
     // as fall back for any other kind use the legacy format
-    return LoadBoard( aFileName, PCB_IO_MGR::LEGACY, aSetActive );
+    return LoadBoard( aFileName, PCB_IO_MGR::LEGACY, aSetActive, aProject );
 }
 
 
-BOARD* LoadBoard( wxString& aFileName )
+BOARD* LoadBoard( const wxString& aFileName )
 {
     return LoadBoard( aFileName, false );
 }
@@ -142,12 +142,13 @@ PROJECT* GetDefaultProject()
     return project;
 }
 
-BOARD* LoadBoard( wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat )
+BOARD* LoadBoard( const wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat )
 {
     return LoadBoard( aFileName, aFormat, false );
 }
 
-BOARD* LoadBoard( wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat, bool aSetActive )
+BOARD* LoadBoard( const wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat, bool aSetActive,
+                  PROJECT* aProject )
 {
     wxFileName pro = aFileName;
     pro.SetExt( FILEEXT::ProjectFileExtension );
@@ -158,7 +159,12 @@ BOARD* LoadBoard( wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat, bool aSet
     // It also avoid wxWidget alerts about locale issues, later, when using Python 3
     LOCALE_IO dummy;
 
-    PROJECT* project = GetSettingsManager()->GetProject( projectPath );
+    PROJECT* project = aProject;
+
+    if( !project )
+    {
+        GetSettingsManager()->GetProject( projectPath );
+    }
 
     if( !project )
     {
@@ -181,7 +187,15 @@ BOARD* LoadBoard( wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat, bool aSet
 
     BASE_SCREEN::m_DrawingSheetFileName = project->GetProjectFile().m_BoardDrawingSheetFile;
 
-    BOARD* brd = PCB_IO_MGR::Load( aFormat, aFileName );
+    BOARD* brd = nullptr;
+    try
+    {
+        brd = PCB_IO_MGR::Load( aFormat, aFileName );
+    }
+    catch( ... )
+    {
+        brd = nullptr;
+    }
 
     if( brd )
     {
diff --git a/pcbnew/python/scripting/pcbnew_scripting_helpers.h b/pcbnew/python/scripting/pcbnew_scripting_helpers.h
index 76f47d1267..7f72a5ebac 100644
--- a/pcbnew/python/scripting/pcbnew_scripting_helpers.h
+++ b/pcbnew/python/scripting/pcbnew_scripting_helpers.h
@@ -55,7 +55,7 @@ BOARD*  GetBoard();
  * This function does not set the board project as the active one
  * @return a pointer to the board if it was created, or None if not
  */
-BOARD*  LoadBoard( wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat );
+BOARD* LoadBoard( const wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat );
 
 #ifndef SWIG
 /**
@@ -63,7 +63,7 @@ BOARD*  LoadBoard( wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat );
  *
  * Hidden from SWIG as aSetActive should not be used by python, but cli also leverages this function
  */
-BOARD* LoadBoard( wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat, bool aSetActive );
+BOARD* LoadBoard( const wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat, bool aSetActive, PROJECT* aProject = nullptr );
 #endif
 
 // Default LoadBoard() to load .kicad_pcb files:.
@@ -75,7 +75,7 @@ BOARD* LoadBoard( wxString& aFileName, PCB_IO_MGR::PCB_FILE_T aFormat, bool aSet
  *
  * Hidden from SWIG as aSetActive should not be used by python, but cli also leverages this function
  */
-BOARD* LoadBoard( wxString& aFileName, bool aSetActive );
+BOARD* LoadBoard( const wxString& aFileName, bool aSetActive, PROJECT* aProject = nullptr );
 #endif
 
 /**
@@ -85,7 +85,7 @@ BOARD* LoadBoard( wxString& aFileName, bool aSetActive );
  * This function does not set the board project as the active one
  * @return a pointer to the board if it was created, or None if not
  */
-BOARD* LoadBoard( wxString& aFileName );
+BOARD* LoadBoard( const wxString& aFileName );
 
 /**
  * Creates a new board and project with the given filename (will overwrite existing files!)
diff --git a/pcbnew/tools/board_editor_control.cpp b/pcbnew/tools/board_editor_control.cpp
index 36a63de0bd..3d0e9b4b78 100644
--- a/pcbnew/tools/board_editor_control.cpp
+++ b/pcbnew/tools/board_editor_control.cpp
@@ -430,7 +430,7 @@ int BOARD_EDITOR_CONTROL::ExportSpecctraDSN( const TOOL_EVENT& aEvent )
 int BOARD_EDITOR_CONTROL::ExportNetlist( const TOOL_EVENT& aEvent )
 {
     wxCHECK( m_frame, 0 );
-
+     
     wxFileName fn = m_frame->Prj().GetProjectFullName();
 
     // Use a different file extension for the board netlist so the schematic netlist file
diff --git a/qa/tests/CMakeLists.txt b/qa/tests/CMakeLists.txt
index a8b68afd18..05424f1937 100644
--- a/qa/tests/CMakeLists.txt
+++ b/qa/tests/CMakeLists.txt
@@ -41,6 +41,7 @@ endif()
     set( NEW_PATHS
 "${CMAKE_BINARY_DIR}/kicad/;\
 ${CMAKE_BINARY_DIR}/common/;\
+${CMAKE_BINARY_DIR}/api/;\
 ${CMAKE_BINARY_DIR}/common/gal/;\
 ${CMAKE_BINARY_DIR}/pcbnew/;\
 ${CMAKE_BINARY_DIR}/eeschema/;\
@@ -55,6 +56,16 @@ if( APPLE )
 ${NEW_PATHS};" )
     get_filename_component( CAIRO_LIB_BASE "${CAIRO_LIBRARY}" DIRECTORY )
     set( EXTRA_PYTEST_ENVIRONMENT "DYLD_FALLBACK_LIBRARY_PATH=${CAIRO_LIB_BASE}" )
+elseif ( MSVC )
+    if( CMAKE_BUILD_TYPE STREQUAL "Debug" )
+        set( NEW_PATHS
+        "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/debug/bin;\
+        ${NEW_PATHS};" )
+    else()
+        set( NEW_PATHS
+        "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin;\
+        ${NEW_PATHS};" )
+    endif()
 endif()
 
 set( QA_PATH_REPLACEMENT "PATH=${NEW_PATHS};$ENV{PATH}" )
diff --git a/qa/tests/cli/test_sch.py b/qa/tests/cli/test_sch.py
index a126cf1252..1553b48824 100644
--- a/qa/tests/cli/test_sch.py
+++ b/qa/tests/cli/test_sch.py
@@ -53,7 +53,7 @@ def test_sch_export_svg( kitest,
     assert stderr == ''
     assert stdout is not None
 
-    stdout_regex = re.match("^Plotted to '(.+)'", stdout)
+    stdout_regex = re.search("Plotted to '(.+)'", stdout)
     assert stdout_regex
 
     # now try and manipulate the extracted path
diff --git a/resources/schemas/jobs.v1.json b/resources/schemas/jobs.v1.json
new file mode 100644
index 0000000000..c31b40a87f
--- /dev/null
+++ b/resources/schemas/jobs.v1.json
@@ -0,0 +1,66 @@
+{
+    "$schema": "http://json-schema.org/draft-07/schema#",
+    "$id": "https://schemas.kicad.org/jobs.v1.json",
+    "title": "KiCad Jobs Schema",
+    "description": "KiCad Jobs",
+    "type": "object",
+    "additionalProperties": false,
+    "properties": {
+        "$schema": {
+          "type": "string",
+          "description": "JSON schema reference"
+        },
+        "meta": {
+          "type": "object",
+            "$ref": "#/definitions/Meta"
+        },    
+        "jobs": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/Job"
+          }
+        },
+    },
+    "required": [
+        "meta",
+        "jobs"
+    ],
+    "definitions": {
+        "Job": {
+          "type": "object",
+          "additionalProperties": false,
+          "properties": {
+            "type": {
+              "type": "string",
+              "description": "Job type",
+              "enum": ["pcb_drill"]
+            },
+            "meta": {
+              "type": "object",
+                "$ref": "#/definitions/Meta"
+            },
+            "settings": {
+              "type": "object"
+            },
+          },
+          "required": [
+            "meta",
+            "type",
+            "settings"
+          ]
+        },
+        "Meta": {
+          "type": "object",
+          "additionalProperties": false,
+          "properties": {
+            "version": {
+              "type": "integer",
+              "description": "File format version"
+            }
+          },
+          "required": [
+            "version"
+          ]
+        },
+    }
+}
\ No newline at end of file