Add the ability to capture job reporting and display it in the result window

This commit is contained in:
Marek Roszko 2024-12-23 23:05:29 -05:00
parent 9c0890302e
commit 62ec7e2d6d
14 changed files with 169 additions and 22 deletions

View File

@ -42,16 +42,26 @@ void JOB_DISPATCHER::Register( const std::string& aJobTypeName,
} }
int JOB_DISPATCHER::RunJob( JOB* job ) int JOB_DISPATCHER::RunJob( JOB* job, REPORTER* aReporter )
{ {
int result = CLI::EXIT_CODES::ERR_UNKNOWN;
REPORTER* existingReporter = m_reporter;
if( aReporter )
{
m_reporter = aReporter;
}
job->ClearExistingOutputs(); job->ClearExistingOutputs();
if( m_jobHandlers.count( job->GetType() ) ) if( m_jobHandlers.count( job->GetType() ) )
{ {
return m_jobHandlers[job->GetType()]( job ); result = m_jobHandlers[job->GetType()]( job );
} }
return CLI::EXIT_CODES::ERR_UNKNOWN; m_reporter = existingReporter;
return result;
} }

View File

@ -38,7 +38,7 @@ public:
JOB_DISPATCHER( KIWAY* aKiway ); JOB_DISPATCHER( KIWAY* aKiway );
void Register( const std::string& aJobTypeName, std::function<int( JOB* job )> aHandler, void Register( const std::string& aJobTypeName, std::function<int( JOB* job )> aHandler,
std::function<bool( JOB* job, wxWindow* aParent )> aConfigHandler ); std::function<bool( JOB* job, wxWindow* aParent )> aConfigHandler );
int RunJob( JOB* aJob ); int RunJob( JOB* aJob, REPORTER* aReporter );
bool HandleJobConfig( JOB* aJob, wxWindow* aParent ); bool HandleJobConfig( JOB* aJob, wxWindow* aParent );
void SetReporter( REPORTER* aReporter ); void SetReporter( REPORTER* aReporter );
void SetProgressReporter( PROGRESS_REPORTER* aReporter ); void SetProgressReporter( PROGRESS_REPORTER* aReporter );

View File

@ -92,7 +92,9 @@ KICOMMON_API void from_json( const nlohmann::json& j, JOBSET_OUTPUT& f )
JOBSET_OUTPUT::JOBSET_OUTPUT() : JOBSET_OUTPUT::JOBSET_OUTPUT() :
m_type( JOBSET_OUTPUT_TYPE::FOLDER ), m_type( JOBSET_OUTPUT_TYPE::FOLDER ),
m_lastRunSuccess() m_outputHandler( nullptr ),
m_lastRunSuccess(),
m_lastRunReporters()
{ {
} }
@ -100,12 +102,24 @@ JOBSET_OUTPUT::JOBSET_OUTPUT() :
JOBSET_OUTPUT::JOBSET_OUTPUT( wxString id, JOBSET_OUTPUT_TYPE type ) : JOBSET_OUTPUT::JOBSET_OUTPUT( wxString id, JOBSET_OUTPUT_TYPE type ) :
m_id( id ), m_id( id ),
m_type( type ), m_type( type ),
m_lastRunSuccess() m_outputHandler( nullptr ),
m_lastRunSuccess(),
m_lastRunReporters()
{ {
InitOutputHandler(); InitOutputHandler();
} }
JOBSET_OUTPUT::~JOBSET_OUTPUT()
{
for( auto& reporter : m_lastRunReporters )
{
delete reporter.second;
}
m_lastRunReporters.clear();
}
void JOBSET_OUTPUT::InitOutputHandler() void JOBSET_OUTPUT::InitOutputHandler()
{ {
if( m_type == JOBSET_OUTPUT_TYPE::FOLDER ) if( m_type == JOBSET_OUTPUT_TYPE::FOLDER )

View File

@ -28,6 +28,8 @@
#include <ctime> #include <ctime>
#include <memory> #include <memory>
class REPORTER;
struct KICOMMON_API JOBSET_JOB struct KICOMMON_API JOBSET_JOB
{ {
JOBSET_JOB() : m_job( nullptr ) {} JOBSET_JOB() : m_job( nullptr ) {}
@ -53,6 +55,8 @@ struct KICOMMON_API JOBSET_OUTPUT
JOBSET_OUTPUT( wxString id, JOBSET_OUTPUT_TYPE type ); JOBSET_OUTPUT( wxString id, JOBSET_OUTPUT_TYPE type );
~JOBSET_OUTPUT();
void InitOutputHandler(); void InitOutputHandler();
wxString m_id; wxString m_id;
@ -63,6 +67,7 @@ struct KICOMMON_API JOBSET_OUTPUT
///< Transient property, not stored for now ///< Transient property, not stored for now
std::optional<bool> m_lastRunSuccess; std::optional<bool> m_lastRunSuccess;
std::unordered_map<wxString, std::optional<bool>> m_lastRunSuccessMap; std::unordered_map<wxString, std::optional<bool>> m_lastRunSuccessMap;
std::unordered_map<wxString, REPORTER*> m_lastRunReporters;
bool operator==( const JOBSET_OUTPUT& rhs ) const; bool operator==( const JOBSET_OUTPUT& rhs ) const;

View File

@ -706,11 +706,11 @@ bool KIWAY::ProcessEvent( wxEvent& aEvent )
} }
int KIWAY::ProcessJob( KIWAY::FACE_T aFace, JOB* job ) int KIWAY::ProcessJob( KIWAY::FACE_T aFace, JOB* job, REPORTER* aReporter )
{ {
KIFACE* kiface = KiFACE( aFace ); KIFACE* kiface = KiFACE( aFace );
return kiface->HandleJob( job ); return kiface->HandleJob( job, aReporter );
} }

View File

@ -344,7 +344,7 @@ static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER
const wxString& aSrcFilePath, wxString& aErrors ) override; const wxString& aSrcFilePath, wxString& aErrors ) override;
int HandleJob( JOB* aJob ) override; int HandleJob( JOB* aJob, REPORTER* aReporter ) override;
bool HandleJobConfig( JOB* aJob, wxWindow* aParent ) override; bool HandleJobConfig( JOB* aJob, wxWindow* aParent ) override;
@ -685,9 +685,9 @@ void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aProje
} }
int IFACE::HandleJob( JOB* aJob ) int IFACE::HandleJob( JOB* aJob, REPORTER* aReporter )
{ {
return m_jobHandler->RunJob( aJob ); return m_jobHandler->RunJob( aJob, aReporter );
} }

View File

@ -133,6 +133,7 @@ class KIWAY_PLAYER;
class wxTopLevelWindow; class wxTopLevelWindow;
class TOOL_ACTION; class TOOL_ACTION;
class JOB; class JOB;
class REPORTER;
/** /**
@ -241,7 +242,7 @@ struct KIFACE
*/ */
virtual void GetActions( std::vector<TOOL_ACTION*>& aActions ) const = 0; virtual void GetActions( std::vector<TOOL_ACTION*>& aActions ) const = 0;
virtual int HandleJob( JOB* aJob ) virtual int HandleJob( JOB* aJob, REPORTER* aReporter )
{ {
return 0; return 0;
} }
@ -431,7 +432,7 @@ public:
bool ProcessEvent( wxEvent& aEvent ) override; bool ProcessEvent( wxEvent& aEvent ) override;
int ProcessJob( KIWAY::FACE_T aFace, JOB* aJob ); int ProcessJob( KIWAY::FACE_T aFace, JOB* aJob, REPORTER* aReporter = nullptr );
bool ProcessJobConfigDialog( KIWAY::FACE_T aFace, JOB* aJob, wxWindow* aWindow ); bool ProcessJobConfigDialog( KIWAY::FACE_T aFace, JOB* aJob, wxWindow* aWindow );
/** /**

View File

@ -225,7 +225,9 @@ public:
DIALOG_OUTPUT_RUN_RESULTS( wxWindow* aParent, DIALOG_OUTPUT_RUN_RESULTS( wxWindow* aParent,
JOBSET* aJobsFile, JOBSET* aJobsFile,
JOBSET_OUTPUT* aOutput ) : JOBSET_OUTPUT* aOutput ) :
DIALOG_OUTPUT_RUN_RESULTS_BASE( aParent ) DIALOG_OUTPUT_RUN_RESULTS_BASE( aParent ),
m_jobsFile( aJobsFile ),
m_output( aOutput )
{ {
m_staticTextOutputName->SetLabel( aOutput->m_outputHandler->GetOutputPath() ); m_staticTextOutputName->SetLabel( aOutput->m_outputHandler->GetOutputPath() );
@ -264,6 +266,33 @@ public:
} }
} }
virtual void OnJobListItemSelected( wxListEvent& event ) override
{
int itemIndex = event.GetIndex();
std::vector<JOBSET_JOB> jobs = m_jobsFile->GetJobsForOutput( m_output );
if( itemIndex < jobs.size() )
{
JOBSET_JOB& job = jobs[itemIndex];
if( m_output->m_lastRunReporters.contains( job.m_id ) )
{
WX_STRING_REPORTER* reporter =
static_cast<WX_STRING_REPORTER*>( m_output->m_lastRunReporters[job.m_id] );
m_textCtrlOutput->SetValue( reporter->GetMessages() );
}
else
{
m_textCtrlOutput->SetValue( _( "No output available" ) );
}
}
}
private:
JOBSET* m_jobsFile;
JOBSET_OUTPUT* m_output;
}; };

View File

@ -362,6 +362,9 @@ DIALOG_OUTPUT_RUN_RESULTS_BASE::DIALOG_OUTPUT_RUN_RESULTS_BASE( wxWindow* parent
m_jobList = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxLC_SINGLE_SEL ); m_jobList = new wxListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxLC_SINGLE_SEL );
bSizer16->Add( m_jobList, 1, wxALL|wxEXPAND, 5 ); bSizer16->Add( m_jobList, 1, wxALL|wxEXPAND, 5 );
m_textCtrlOutput = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_BESTWRAP|wxTE_MULTILINE|wxTE_READONLY );
bSizer16->Add( m_textCtrlOutput, 1, wxALL|wxEXPAND, 5 );
bMainSizer->Add( bSizer16, 1, wxEXPAND, 5 ); bMainSizer->Add( bSizer16, 1, wxEXPAND, 5 );
@ -380,12 +383,14 @@ DIALOG_OUTPUT_RUN_RESULTS_BASE::DIALOG_OUTPUT_RUN_RESULTS_BASE( wxWindow* parent
this->Centre( wxBOTH ); this->Centre( wxBOTH );
// Connect Events // Connect Events
m_jobList->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( DIALOG_OUTPUT_RUN_RESULTS_BASE::OnJobListItemSelected ), NULL, this );
m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_OUTPUT_RUN_RESULTS_BASE::OnButtonOk ), NULL, this ); m_sdbSizerOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_OUTPUT_RUN_RESULTS_BASE::OnButtonOk ), NULL, this );
} }
DIALOG_OUTPUT_RUN_RESULTS_BASE::~DIALOG_OUTPUT_RUN_RESULTS_BASE() DIALOG_OUTPUT_RUN_RESULTS_BASE::~DIALOG_OUTPUT_RUN_RESULTS_BASE()
{ {
// Disconnect Events // Disconnect Events
m_jobList->Disconnect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEventHandler( DIALOG_OUTPUT_RUN_RESULTS_BASE::OnJobListItemSelected ), NULL, this );
m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_OUTPUT_RUN_RESULTS_BASE::OnButtonOk ), NULL, this ); m_sdbSizerOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_OUTPUT_RUN_RESULTS_BASE::OnButtonOk ), NULL, this );
} }

View File

@ -2487,7 +2487,7 @@
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
<object class="wxBoxSizer" expanded="false"> <object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">bMainSizer</property> <property name="name">bMainSizer</property>
<property name="orient">wxVERTICAL</property> <property name="orient">wxVERTICAL</property>
@ -2554,11 +2554,11 @@
<property name="wrap">-1</property> <property name="wrap">-1</property>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="false"> <object class="sizeritem" expanded="true">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxEXPAND</property> <property name="flag">wxEXPAND</property>
<property name="proportion">1</property> <property name="proportion">1</property>
<object class="wxBoxSizer" expanded="false"> <object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">bSizer16</property> <property name="name">bSizer16</property>
<property name="orient">wxHORIZONTAL</property> <property name="orient">wxHORIZONTAL</property>
@ -2624,6 +2624,72 @@
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
<event name="OnListItemSelected">OnJobListItemSelected</event>
</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="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"></property>
<property name="moveable">1</property>
<property name="name">m_textCtrlOutput</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_BESTWRAP|wxTE_MULTILINE|wxTE_READONLY</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> </object>

View File

@ -180,10 +180,12 @@ class DIALOG_OUTPUT_RUN_RESULTS_BASE : public DIALOG_SHIM
protected: protected:
wxStaticText* m_staticTextOutputName; wxStaticText* m_staticTextOutputName;
wxListCtrl* m_jobList; wxListCtrl* m_jobList;
wxTextCtrl* m_textCtrlOutput;
wxStdDialogButtonSizer* m_sdbSizer; wxStdDialogButtonSizer* m_sdbSizer;
wxButton* m_sdbSizerOK; wxButton* m_sdbSizerOK;
// Virtual event handlers, override them in your derived class // Virtual event handlers, override them in your derived class
virtual void OnJobListItemSelected( wxListEvent& event ) { event.Skip(); }
virtual void OnButtonOk( wxCommandEvent& event ) { event.Skip(); } virtual void OnButtonOk( wxCommandEvent& event ) { event.Skip(); }

View File

@ -100,6 +100,12 @@ bool JOBS_RUNNER::RunJobsForOutput( JOBSET_OUTPUT* aOutput, bool aBail )
aOutput->m_lastRunSuccessMap.clear(); aOutput->m_lastRunSuccessMap.clear();
for( auto& reporter : aOutput->m_lastRunReporters )
{
delete reporter.second;
}
aOutput->m_lastRunReporters.clear();
wxString tempDirPath = tmp.GetFullPath(); wxString tempDirPath = tmp.GetFullPath();
if( !wxFileName::Mkdir( tempDirPath, wxS_DIR_DEFAULT ) ) if( !wxFileName::Mkdir( tempDirPath, wxS_DIR_DEFAULT ) )
{ {
@ -131,7 +137,7 @@ bool JOBS_RUNNER::RunJobsForOutput( JOBSET_OUTPUT* aOutput, bool aBail )
{ {
msg += wxT( "|--------------------------------\n" ); msg += wxT( "|--------------------------------\n" );
msg += wxT( "| " ); msg += wxT( "| " );
msg += wxString::Format( "Performing jobs" ); msg += wxString::Format( "Performing jobs for output %s", aOutput->m_id );
msg += wxT( "\n" ); msg += wxT( "\n" );
msg += wxT( "|--------------------------------\n" ); msg += wxT( "|--------------------------------\n" );
@ -172,10 +178,17 @@ bool JOBS_RUNNER::RunJobsForOutput( JOBSET_OUTPUT* aOutput, bool aBail )
job.m_job->SetTempOutputDirectory( tempDirPath ); job.m_job->SetTempOutputDirectory( tempDirPath );
REPORTER* reporterToUse = m_reporter;
if( !reporterToUse || reporterToUse == &NULL_REPORTER::GetInstance() )
{
reporterToUse = new WX_STRING_REPORTER;
aOutput->m_lastRunReporters[job.m_id] = reporterToUse;
}
int result = 0; int result = 0;
if( iface < KIWAY::KIWAY_FACE_COUNT ) if( iface < KIWAY::KIWAY_FACE_COUNT )
{ {
result = m_kiway->ProcessJob( iface, job.m_job.get() ); result = m_kiway->ProcessJob( iface, job.m_job.get(), reporterToUse );
} }
else else
{ {

View File

@ -336,7 +336,7 @@ static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER
const wxString& aNewProjectBasePath, const wxString& aNewProjectName, const wxString& aNewProjectBasePath, const wxString& aNewProjectName,
const wxString& aSrcFilePath, wxString& aErrors ) override; const wxString& aSrcFilePath, wxString& aErrors ) override;
int HandleJob( JOB* aJob ) override; int HandleJob( JOB* aJob, REPORTER* aReporter ) override;
bool HandleJobConfig( JOB* aJob, wxWindow* aParent ) override; bool HandleJobConfig( JOB* aJob, wxWindow* aParent ) override;
@ -568,9 +568,9 @@ void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcPr
} }
int IFACE::HandleJob( JOB* aJob ) int IFACE::HandleJob( JOB* aJob, REPORTER* aReporter )
{ {
return m_jobHandler->RunJob( aJob ); return m_jobHandler->RunJob( aJob, aReporter );
} }

View File

@ -347,6 +347,7 @@ int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob )
case JOB_EXPORT_PCB_3D::FORMAT::STL: fn.SetExt( FILEEXT::StlFileExtension ); case JOB_EXPORT_PCB_3D::FORMAT::STL: fn.SetExt( FILEEXT::StlFileExtension );
break; break;
default: default:
m_reporter->Report( _( "Unknown export format" ), RPT_SEVERITY_ERROR );
return CLI::EXIT_CODES::ERR_UNKNOWN; // shouldnt have gotten here return CLI::EXIT_CODES::ERR_UNKNOWN; // shouldnt have gotten here
} }
@ -421,6 +422,7 @@ int PCBNEW_JOBS_HANDLER::JobExportStep( JOB* aJob )
params.m_Format = EXPORTER_STEP_PARAMS::FORMAT::STL; params.m_Format = EXPORTER_STEP_PARAMS::FORMAT::STL;
break; break;
default: default:
m_reporter->Report( _( "Unknown export format" ), RPT_SEVERITY_ERROR );
return CLI::EXIT_CODES::ERR_UNKNOWN; // shouldnt have gotten here return CLI::EXIT_CODES::ERR_UNKNOWN; // shouldnt have gotten here
} }