2024-07-15 18:20:13 -04:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2024 Mark Roszko <mark.roszko@gmail.com>
|
2025-01-01 13:30:11 -08:00
|
|
|
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
2024-07-15 18:20:13 -04:00
|
|
|
*
|
|
|
|
* 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"
|
2025-01-12 12:11:56 +00:00
|
|
|
#include "dialog_job_output_options.h"
|
2025-01-04 13:06:09 +00:00
|
|
|
#include "dialog_copyfiles_job_settings.h"
|
2024-07-15 18:20:13 -04:00
|
|
|
#include <wx/aui/auibook.h>
|
|
|
|
#include <jobs/jobset.h>
|
|
|
|
#include <jobs/job_registry.h>
|
|
|
|
#include <eda_list_dialog.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 <kicad_manager_frame.h>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include <wildcards_and_files_ext.h>
|
|
|
|
#include <widgets/std_bitmap_button.h>
|
2024-12-30 18:23:34 +00:00
|
|
|
#include <widgets/wx_grid.h>
|
|
|
|
#include <widgets/grid_text_button_helpers.h>
|
|
|
|
#include <kiplatform/ui.h>
|
2024-07-15 18:20:13 -04:00
|
|
|
#include <confirm.h>
|
|
|
|
|
2024-10-22 22:29:14 -04:00
|
|
|
#include <jobs/job_special_execute.h>
|
2025-01-01 23:57:14 -05:00
|
|
|
#include <jobs/job_special_copyfiles.h>
|
2025-01-04 13:06:09 +00:00
|
|
|
#include <dialogs/dialog_executecommand_job_settings.h>
|
2024-10-22 22:29:14 -04:00
|
|
|
|
2024-07-15 18:20:13 -04:00
|
|
|
|
2025-01-12 14:14:35 +00:00
|
|
|
extern KICOMMON_API std::map<JOBSET_OUTPUT_TYPE, JOBSET_OUTPUT_TYPE_INFO> JobsetOutputTypeInfos;
|
2024-07-15 18:20:13 -04:00
|
|
|
|
|
|
|
|
2024-12-16 22:32:22 -05:00
|
|
|
class DIALOG_OUTPUT_RUN_RESULTS : public DIALOG_OUTPUT_RUN_RESULTS_BASE
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DIALOG_OUTPUT_RUN_RESULTS( wxWindow* aParent,
|
|
|
|
JOBSET* aJobsFile,
|
|
|
|
JOBSET_OUTPUT* aOutput ) :
|
2024-12-23 23:05:29 -05:00
|
|
|
DIALOG_OUTPUT_RUN_RESULTS_BASE( aParent ),
|
|
|
|
m_jobsFile( aJobsFile ),
|
|
|
|
m_output( aOutput )
|
2024-12-16 22:32:22 -05:00
|
|
|
{
|
2025-01-04 15:40:47 +00:00
|
|
|
m_staticTextOutputName->SetLabel( wxString::Format( _( "Output: %s" ),
|
|
|
|
aOutput->GetDescription() ) );
|
2024-12-16 22:32:22 -05:00
|
|
|
|
2024-12-19 16:42:59 -08:00
|
|
|
int jobBmpColId = m_jobList->AppendColumn( wxT( "" ) );
|
2024-12-16 22:32:22 -05:00
|
|
|
int jobNoColId = m_jobList->AppendColumn( _( "No." ) );
|
|
|
|
int jobDescColId = m_jobList->AppendColumn( _( "Job Description" ) );
|
|
|
|
m_jobList->SetColumnWidth( jobBmpColId, wxLIST_AUTOSIZE_USEHEADER );
|
|
|
|
m_jobList->SetColumnWidth( jobNoColId, wxLIST_AUTOSIZE_USEHEADER );
|
|
|
|
m_jobList->SetColumnWidth( jobDescColId, wxLIST_AUTOSIZE_USEHEADER );
|
|
|
|
|
|
|
|
wxImageList* imageList = new wxImageList( 16, 16, true, 3 );
|
|
|
|
imageList->Add( KiBitmapBundle( BITMAPS::ercerr ).GetBitmap( wxSize( 16, 16 ) ) );
|
|
|
|
imageList->Add( KiBitmapBundle( BITMAPS::checked_ok ).GetBitmap( wxSize( 16, 16 ) ) );
|
|
|
|
m_jobList->SetImageList( imageList, wxIMAGE_LIST_SMALL );
|
|
|
|
|
|
|
|
int num = 1;
|
|
|
|
for( auto& job : aJobsFile->GetJobsForOutput( aOutput ) )
|
|
|
|
{
|
|
|
|
int imageIdx = -1;
|
|
|
|
if( aOutput->m_lastRunSuccessMap.contains( job.m_id ) )
|
|
|
|
{
|
|
|
|
if( aOutput->m_lastRunSuccessMap[job.m_id].value() )
|
|
|
|
imageIdx = 1;
|
|
|
|
else
|
|
|
|
imageIdx = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
long itemIndex = m_jobList->InsertItem( m_jobList->GetItemCount(), imageIdx );
|
|
|
|
|
|
|
|
m_jobList->SetItem( itemIndex, jobNoColId, wxString::Format( "%d", num++ ) );
|
2024-12-28 21:18:15 -05:00
|
|
|
m_jobList->SetItem( itemIndex, jobDescColId, job.GetDescription() );
|
2024-12-16 22:32:22 -05:00
|
|
|
}
|
2025-01-04 15:40:47 +00:00
|
|
|
|
|
|
|
SetupStandardButtons( { { wxID_OK, _( "Close" ) } } );
|
2024-12-16 22:32:22 -05:00
|
|
|
}
|
|
|
|
|
2024-12-23 23:05:29 -05:00
|
|
|
|
|
|
|
virtual void OnJobListItemSelected( wxListEvent& event ) override
|
|
|
|
{
|
|
|
|
int itemIndex = event.GetIndex();
|
|
|
|
|
2024-12-30 17:12:36 +00:00
|
|
|
// The index could be negative (it is default -1)
|
|
|
|
if( itemIndex < 0 )
|
|
|
|
return;
|
|
|
|
|
2024-12-23 23:05:29 -05:00
|
|
|
std::vector<JOBSET_JOB> jobs = m_jobsFile->GetJobsForOutput( m_output );
|
|
|
|
|
2024-12-30 17:12:36 +00:00
|
|
|
if( static_cast<size_t>( itemIndex ) < jobs.size() )
|
2024-12-23 23:05:29 -05:00
|
|
|
{
|
|
|
|
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
|
|
|
|
{
|
2024-12-31 05:04:21 +05:00
|
|
|
m_textCtrlOutput->SetValue( _( "No output messages" ) );
|
2024-12-23 23:05:29 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
JOBSET* m_jobsFile;
|
|
|
|
JOBSET_OUTPUT* m_output;
|
2024-12-16 22:32:22 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2024-07-15 18:20:13 -04:00
|
|
|
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 ),
|
2025-01-12 10:54:45 +00:00
|
|
|
m_outputId( aOutput->m_id ),
|
2024-07-15 18:20:13 -04:00
|
|
|
m_frame( aFrame ),
|
|
|
|
m_panelParent( aPanelParent )
|
|
|
|
{
|
2025-01-04 22:56:29 +00:00
|
|
|
m_buttonProperties->SetBitmap( KiBitmapBundle( BITMAPS::config ) );
|
2025-01-03 17:41:37 +00:00
|
|
|
m_buttonDelete->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
|
2024-07-15 18:20:13 -04:00
|
|
|
|
2025-01-03 19:52:43 -05:00
|
|
|
#if _WIN32
|
|
|
|
// BORDER_RAISED/SUNKEN look pretty on every platform but Windows
|
|
|
|
long style = GetWindowStyleFlag();
|
|
|
|
style &= ~wxBORDER_MASK;
|
|
|
|
style |= wxBORDER_SIMPLE;
|
|
|
|
SetWindowStyleFlag( style );
|
|
|
|
#endif // _WIN32
|
|
|
|
|
2025-01-03 17:41:37 +00:00
|
|
|
Connect( wxEVT_MENU, wxCommandEventHandler( PANEL_JOB_OUTPUT::onMenu ), nullptr, this );
|
2024-07-15 18:20:13 -04:00
|
|
|
|
2025-01-12 12:11:56 +00:00
|
|
|
if( JobsetOutputTypeInfos.contains( aOutput->m_type ) )
|
2024-07-15 18:20:13 -04:00
|
|
|
{
|
2025-01-12 12:11:56 +00:00
|
|
|
JOBSET_OUTPUT_TYPE_INFO& jobTypeInfo = JobsetOutputTypeInfos[aOutput->m_type];
|
2024-12-29 07:16:38 -05:00
|
|
|
m_textOutputType->SetLabel( aOutput->GetDescription() );
|
2024-07-15 18:20:13 -04:00
|
|
|
m_bitmapOutputType->SetBitmap( KiBitmapBundle( jobTypeInfo.bitmap ) );
|
|
|
|
}
|
2024-12-26 11:24:32 -05:00
|
|
|
|
|
|
|
UpdateStatus();
|
2024-07-15 18:20:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
~PANEL_JOB_OUTPUT()
|
|
|
|
{
|
2025-01-03 17:41:37 +00:00
|
|
|
Disconnect( wxEVT_MENU, wxCommandEventHandler( PANEL_JOB_OUTPUT::onMenu ), nullptr, this );
|
2024-07-15 18:20:13 -04:00
|
|
|
}
|
|
|
|
|
2024-12-16 22:32:22 -05:00
|
|
|
void UpdateStatus()
|
|
|
|
{
|
2025-01-12 10:54:45 +00:00
|
|
|
JOBSET_OUTPUT* output = GetOutput();
|
|
|
|
wxCHECK( output, /*void*/ );
|
|
|
|
|
|
|
|
if( output->m_lastRunSuccess.has_value() )
|
2024-12-16 22:32:22 -05:00
|
|
|
{
|
2025-01-12 10:54:45 +00:00
|
|
|
if( output->m_lastRunSuccess.value() )
|
2024-12-16 22:32:22 -05:00
|
|
|
{
|
|
|
|
m_statusBitmap->SetBitmap( KiBitmapBundle( BITMAPS::checked_ok ) );
|
|
|
|
m_statusBitmap->Show();
|
|
|
|
m_statusBitmap->SetToolTip( _( "Last run successful" ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_statusBitmap->SetBitmap( KiBitmapBundle( BITMAPS::ercerr ) );
|
|
|
|
m_statusBitmap->Show();
|
|
|
|
m_statusBitmap->SetToolTip( _( "Last run failed" ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2025-01-01 14:29:26 +00:00
|
|
|
m_statusBitmap->SetBitmap( wxNullBitmap );
|
2024-12-16 22:32:22 -05:00
|
|
|
}
|
2024-12-26 11:24:32 -05:00
|
|
|
|
2025-01-12 10:54:45 +00:00
|
|
|
m_buttonGenerate->Enable( !m_jobsFile->GetJobsForOutput( output ).empty() );
|
2024-12-16 22:32:22 -05:00
|
|
|
}
|
|
|
|
|
2025-01-03 17:41:37 +00:00
|
|
|
virtual void OnGenerate( wxCommandEvent& event ) override
|
2024-07-15 18:20:13 -04:00
|
|
|
{
|
|
|
|
CallAfter(
|
|
|
|
[this]()
|
|
|
|
{
|
|
|
|
PROJECT& project = m_frame->Kiway().Prj();
|
|
|
|
m_panelParent->EnsurePcbSchFramesOpen();
|
|
|
|
|
|
|
|
wxFileName fn = project.GetProjectFullName();
|
|
|
|
wxSetWorkingDirectory( fn.GetPath() );
|
|
|
|
|
2024-12-24 11:44:22 -05:00
|
|
|
JOBS_RUNNER jobRunner( &( m_frame->Kiway() ), m_jobsFile, &project );
|
2024-07-15 18:20:13 -04:00
|
|
|
|
|
|
|
WX_PROGRESS_REPORTER* progressReporter =
|
|
|
|
new WX_PROGRESS_REPORTER( m_frame, _( "Running jobs" ), 1 );
|
|
|
|
|
2025-01-12 10:54:45 +00:00
|
|
|
if( JOBSET_OUTPUT* output = GetOutput() )
|
|
|
|
jobRunner.RunJobsForOutput( output );
|
|
|
|
|
2024-12-16 22:32:22 -05:00
|
|
|
UpdateStatus();
|
2024-07-15 18:20:13 -04:00
|
|
|
|
|
|
|
delete progressReporter;
|
2025-01-12 10:58:43 +00:00
|
|
|
|
|
|
|
// Bring the Kicad manager frame back to the front
|
|
|
|
m_frame->Raise();
|
2024-07-15 18:20:13 -04:00
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
2025-01-03 17:41:37 +00:00
|
|
|
virtual void OnLastStatusClick( wxMouseEvent& aEvent ) override
|
2024-12-16 22:32:22 -05:00
|
|
|
{
|
2025-01-12 10:54:45 +00:00
|
|
|
JOBSET_OUTPUT* output = GetOutput();
|
|
|
|
wxCHECK( output, /*void*/ );
|
|
|
|
|
|
|
|
DIALOG_OUTPUT_RUN_RESULTS dialog( m_frame, m_jobsFile, output );
|
2024-12-16 22:32:22 -05:00
|
|
|
dialog.ShowModal();
|
|
|
|
}
|
|
|
|
|
2025-01-03 17:41:37 +00:00
|
|
|
void OnRightDown( wxMouseEvent& aEvent ) override
|
2024-07-15 18:20:13 -04:00
|
|
|
{
|
2025-01-12 10:54:45 +00:00
|
|
|
JOBSET_OUTPUT* output = GetOutput();
|
|
|
|
wxCHECK( output, /*void*/ );
|
|
|
|
|
2024-07-15 18:20:13 -04:00
|
|
|
wxMenu menu;
|
2025-01-03 17:41:37 +00:00
|
|
|
menu.Append( wxID_EDIT, _( "Edit Output Options..." ) );
|
|
|
|
menu.Append( wxID_DELETE, _( "Delete Output" ) );
|
2024-07-15 18:20:13 -04:00
|
|
|
|
2025-01-03 17:41:37 +00:00
|
|
|
menu.AppendSeparator();
|
|
|
|
menu.Append( wxID_VIEW_DETAILS, _( "View Last Run Results..." ) );
|
|
|
|
|
2025-01-12 10:54:45 +00:00
|
|
|
menu.Enable( wxID_VIEW_DETAILS, output->m_lastRunSuccess.has_value() );
|
2025-01-03 17:41:37 +00:00
|
|
|
|
|
|
|
PopupMenu( &menu );
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnProperties( wxCommandEvent& aEvent ) override
|
|
|
|
{
|
2025-01-12 10:54:45 +00:00
|
|
|
JOBSET_OUTPUT* output = GetOutput();
|
|
|
|
wxCHECK( output, /*void*/ );
|
|
|
|
|
|
|
|
DIALOG_JOB_OUTPUT_OPTIONS dialog( m_frame, m_jobsFile, output );
|
2025-01-03 17:41:37 +00:00
|
|
|
|
|
|
|
if( dialog.ShowModal() == wxID_OK )
|
2024-12-16 22:32:22 -05:00
|
|
|
{
|
2025-01-12 10:54:45 +00:00
|
|
|
m_textOutputType->SetLabel( output->GetDescription() );
|
2025-01-03 17:41:37 +00:00
|
|
|
m_jobsFile->SetDirty();
|
|
|
|
m_panelParent->UpdateTitle();
|
2024-12-16 22:32:22 -05:00
|
|
|
}
|
2024-07-15 18:20:13 -04:00
|
|
|
}
|
|
|
|
|
2025-01-03 17:41:37 +00:00
|
|
|
virtual void OnDelete( wxCommandEvent& aEvent ) override
|
|
|
|
{
|
2025-01-12 10:54:45 +00:00
|
|
|
m_panelParent->RemoveOutput( this );
|
|
|
|
}
|
|
|
|
|
|
|
|
JOBSET_OUTPUT* GetOutput()
|
|
|
|
{
|
|
|
|
for( JOBSET_OUTPUT& jobset : m_jobsFile->GetOutputs() )
|
|
|
|
{
|
|
|
|
if( jobset.m_id == m_outputId )
|
|
|
|
return &jobset;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
2025-01-03 17:41:37 +00:00
|
|
|
}
|
2024-07-15 18:20:13 -04:00
|
|
|
|
|
|
|
private:
|
|
|
|
void onMenu( wxCommandEvent& aEvent )
|
|
|
|
{
|
|
|
|
switch( aEvent.GetId() )
|
|
|
|
{
|
|
|
|
case wxID_EDIT:
|
|
|
|
{
|
2025-01-03 17:41:37 +00:00
|
|
|
wxCommandEvent dummy;
|
|
|
|
OnProperties( dummy );
|
2024-07-15 18:20:13 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case wxID_DELETE:
|
2025-01-03 17:41:37 +00:00
|
|
|
{
|
|
|
|
wxCommandEvent dummy;
|
|
|
|
OnDelete( dummy );
|
|
|
|
}
|
2024-07-15 18:20:13 -04:00
|
|
|
break;
|
|
|
|
|
2024-12-16 22:32:22 -05:00
|
|
|
case wxID_VIEW_DETAILS:
|
|
|
|
{
|
2025-01-03 17:41:37 +00:00
|
|
|
wxMouseEvent dummy;
|
|
|
|
OnLastStatusClick( dummy );
|
2024-12-16 22:32:22 -05:00
|
|
|
}
|
2025-01-03 17:41:37 +00:00
|
|
|
break;
|
2024-12-16 22:32:22 -05:00
|
|
|
|
2024-07-15 18:20:13 -04:00
|
|
|
default:
|
|
|
|
wxFAIL_MSG( wxT( "Unknown ID in context menu event" ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-01-03 17:41:37 +00:00
|
|
|
private:
|
2024-12-30 21:12:41 +00:00
|
|
|
JOBSET* m_jobsFile;
|
2025-01-12 10:54:45 +00:00
|
|
|
wxString m_outputId;
|
2024-07-15 18:20:13 -04:00
|
|
|
KICAD_MANAGER_FRAME* m_frame;
|
|
|
|
PANEL_JOBS* m_panelParent;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2024-12-30 18:23:34 +00:00
|
|
|
JOBS_GRID_TRICKS::JOBS_GRID_TRICKS( PANEL_JOBS* aParent, WX_GRID* aGrid ) :
|
|
|
|
GRID_TRICKS( aGrid ),
|
|
|
|
m_parent( aParent )
|
|
|
|
{
|
2024-12-30 21:12:41 +00:00
|
|
|
m_enableSingleClickEdit = false;
|
2024-12-30 18:23:34 +00:00
|
|
|
m_multiCellEditEnabled = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-12-30 21:12:41 +00:00
|
|
|
void JOBS_GRID_TRICKS::showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
|
2024-12-30 18:23:34 +00:00
|
|
|
{
|
2024-12-30 21:12:41 +00:00
|
|
|
wxArrayInt selectedRows = m_grid->GetSelectedRows();
|
|
|
|
|
|
|
|
menu.Append( JOB_DESCRIPTION, _( "Edit Job Description" ) );
|
|
|
|
menu.Append( JOB_PROPERTIES, _( "Edit Job Settings..." ) );
|
|
|
|
menu.AppendSeparator();
|
|
|
|
menu.Append( GRIDTRICKS_ID_COPY, _( "Copy" ) + "\tCtrl+C",
|
|
|
|
_( "Copy selected cells to clipboard" ) );
|
|
|
|
menu.Append( GRIDTRICKS_ID_DELETE, _( "Delete" ) + "\tDel",
|
|
|
|
_( "Delete selected jobs" ) );
|
|
|
|
menu.Append( GRIDTRICKS_ID_SELECT, _( "Select All" ) + "\tCtrl+A",
|
|
|
|
_( "Select all jobs" ) );
|
|
|
|
|
|
|
|
menu.Enable( JOB_DESCRIPTION, selectedRows.size() == 1 );
|
|
|
|
menu.Enable( JOB_PROPERTIES, selectedRows.size() == 1 );
|
|
|
|
menu.Enable( GRIDTRICKS_ID_DELETE, selectedRows.size() > 0 );
|
|
|
|
|
|
|
|
m_grid->PopupMenu( &menu );
|
|
|
|
}
|
2024-12-30 18:23:34 +00:00
|
|
|
|
|
|
|
|
2024-12-30 21:12:41 +00:00
|
|
|
void JOBS_GRID_TRICKS::doPopupSelection( wxCommandEvent& event )
|
|
|
|
{
|
|
|
|
wxArrayInt selectedRows = m_grid->GetSelectedRows();
|
|
|
|
|
|
|
|
if( event.GetId() == JOB_DESCRIPTION )
|
2024-12-30 18:23:34 +00:00
|
|
|
{
|
2024-12-30 21:12:41 +00:00
|
|
|
if( selectedRows.size() > 0 )
|
|
|
|
{
|
|
|
|
m_grid->SetGridCursor( selectedRows[0], 1 );
|
|
|
|
m_grid->EnableCellEditControl();
|
|
|
|
}
|
2024-12-30 18:23:34 +00:00
|
|
|
}
|
2024-12-30 21:12:41 +00:00
|
|
|
else if( event.GetId() == JOB_PROPERTIES )
|
2024-12-30 18:23:34 +00:00
|
|
|
{
|
2024-12-30 21:12:41 +00:00
|
|
|
if( selectedRows.size() > 0 )
|
|
|
|
m_parent->OpenJobOptionsForListItem( selectedRows[0] );
|
2024-12-30 18:23:34 +00:00
|
|
|
}
|
2024-12-30 21:12:41 +00:00
|
|
|
else if( event.GetId() == GRIDTRICKS_ID_DELETE )
|
|
|
|
{
|
|
|
|
wxCommandEvent dummy;
|
|
|
|
m_parent->OnJobButtonDelete( dummy );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GRID_TRICKS::doPopupSelection( event );
|
|
|
|
}
|
|
|
|
}
|
2024-12-30 18:23:34 +00:00
|
|
|
|
|
|
|
|
2024-12-30 21:12:41 +00:00
|
|
|
bool JOBS_GRID_TRICKS::handleDoubleClick( wxGridEvent& aEvent )
|
2024-12-30 18:23:34 +00:00
|
|
|
{
|
2024-12-31 17:47:59 +00:00
|
|
|
m_grid->CancelShowEditorOnMouseUp();
|
|
|
|
|
2025-01-06 12:41:46 +01:00
|
|
|
int curr_col = aEvent.GetCol();
|
|
|
|
int curr_row = aEvent.GetRow();
|
2024-12-30 18:23:34 +00:00
|
|
|
|
2025-01-06 12:41:46 +01:00
|
|
|
if( ( curr_col == 0 || curr_col == 1 )
|
|
|
|
&& curr_row >= 0 && curr_row < (int) m_parent->GetJobsFile()->GetJobs().size() )
|
2024-12-30 18:23:34 +00:00
|
|
|
{
|
2025-01-06 12:41:46 +01:00
|
|
|
m_doubleClickRow = curr_row;
|
2025-01-03 18:31:34 +00:00
|
|
|
m_grid->CancelPendingChanges();
|
|
|
|
|
|
|
|
CallAfter(
|
|
|
|
[this]()
|
|
|
|
{
|
|
|
|
// Yes, again. CancelShowEditorOnMouseUp() doesn't appear to be 100%
|
|
|
|
// reliable.
|
|
|
|
m_grid->CancelPendingChanges();
|
|
|
|
int row = m_doubleClickRow;
|
|
|
|
m_doubleClickRow = -1;
|
|
|
|
|
|
|
|
if( row >= 0 && row < (int) m_parent->GetJobsFile()->GetJobs().size() )
|
|
|
|
m_parent->OpenJobOptionsForListItem( row );
|
|
|
|
} );
|
|
|
|
|
2024-12-30 21:12:41 +00:00
|
|
|
return true;
|
2024-12-30 18:23:34 +00:00
|
|
|
}
|
|
|
|
|
2024-12-30 21:12:41 +00:00
|
|
|
return false;
|
|
|
|
}
|
2024-12-30 18:23:34 +00:00
|
|
|
|
|
|
|
|
2024-07-15 18:20:13 -04:00
|
|
|
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 ) )
|
|
|
|
{
|
2024-12-30 18:23:34 +00:00
|
|
|
m_jobsGrid->PushEventHandler( new JOBS_GRID_TRICKS( this, m_jobsGrid ) );
|
|
|
|
|
2024-12-30 21:12:41 +00:00
|
|
|
m_jobsGrid->SetDefaultRowSize( m_jobsGrid->GetDefaultRowSize() + 4 );
|
2024-12-31 13:07:26 +00:00
|
|
|
m_jobsGrid->OverrideMinSize( 0.6, 0.3 );
|
2025-01-06 13:04:05 +00:00
|
|
|
m_jobsGrid->SetSelectionMode( wxGrid::wxGridSelectRows );
|
2024-07-15 18:20:13 -04:00
|
|
|
|
2025-01-01 20:34:17 +00:00
|
|
|
// 'm' for margins
|
|
|
|
m_jobsGrid->SetColSize( 0, GetTextExtent( wxT( "99m" ) ).x );
|
|
|
|
|
2024-07-15 18:20:13 -04:00
|
|
|
m_buttonAddJob->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
|
|
|
|
m_buttonUp->SetBitmap( KiBitmapBundle( BITMAPS::small_up ) );
|
|
|
|
m_buttonDown->SetBitmap( KiBitmapBundle( BITMAPS::small_down ) );
|
2024-12-30 18:23:34 +00:00
|
|
|
m_buttonDelete->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
|
2024-07-15 18:20:13 -04:00
|
|
|
m_buttonOutputAdd->SetBitmap( KiBitmapBundle( BITMAPS::small_plus ) );
|
|
|
|
|
|
|
|
rebuildJobList();
|
|
|
|
buildOutputList();
|
2024-11-07 07:25:40 -05:00
|
|
|
|
2024-12-30 18:23:34 +00:00
|
|
|
m_buttonRunAllOutputs->Enable( !m_jobsFile->GetOutputs().empty()
|
|
|
|
&& !m_jobsFile->GetJobs().empty() );
|
2024-07-15 18:20:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-10-03 08:02:21 -04:00
|
|
|
PANEL_JOBS::~PANEL_JOBS()
|
|
|
|
{
|
2024-12-30 18:23:34 +00:00
|
|
|
// Delete the GRID_TRICKS.
|
|
|
|
m_jobsGrid->PopEventHandler( true );
|
2024-10-03 08:02:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2025-01-12 10:54:45 +00:00
|
|
|
void PANEL_JOBS::RemoveOutput( PANEL_JOB_OUTPUT* aPanel )
|
2024-07-15 18:20:13 -04:00
|
|
|
{
|
2025-01-12 10:54:45 +00:00
|
|
|
JOBSET_OUTPUT* output = aPanel->GetOutput();
|
2024-12-30 21:12:41 +00:00
|
|
|
|
2025-01-12 10:54:45 +00:00
|
|
|
m_outputListSizer->Detach( aPanel );
|
|
|
|
aPanel->Destroy();
|
2024-07-15 18:20:13 -04:00
|
|
|
|
2025-01-12 10:54:45 +00:00
|
|
|
// ensure the window contents get shifted as needed
|
|
|
|
m_outputList->Layout();
|
|
|
|
Layout();
|
2024-07-15 18:20:13 -04:00
|
|
|
|
2025-01-12 10:54:45 +00:00
|
|
|
m_jobsFile->RemoveOutput( output );
|
2024-11-07 07:25:40 -05:00
|
|
|
|
|
|
|
m_buttonRunAllOutputs->Enable( !m_jobsFile->GetOutputs().empty() );
|
2024-07-15 18:20:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PANEL_JOBS::rebuildJobList()
|
|
|
|
{
|
2024-12-30 18:23:34 +00:00
|
|
|
if( m_jobsGrid->GetNumberRows() )
|
|
|
|
m_jobsGrid->DeleteRows( 0, m_jobsGrid->GetNumberRows() );
|
|
|
|
|
|
|
|
m_jobsGrid->AppendRows( m_jobsFile->GetJobs().size() );
|
2024-07-15 18:20:13 -04:00
|
|
|
|
|
|
|
int num = 1;
|
2024-12-30 18:23:34 +00:00
|
|
|
|
|
|
|
for( JOBSET_JOB& job : m_jobsFile->GetJobs() )
|
2024-07-15 18:20:13 -04:00
|
|
|
{
|
2024-12-30 18:23:34 +00:00
|
|
|
m_jobsGrid->SetCellValue( num - 1, 0, wxString::Format( "%d", num ) );
|
|
|
|
m_jobsGrid->SetReadOnly( num - 1, 0 );
|
|
|
|
|
|
|
|
m_jobsGrid->SetCellValue( num - 1, 1, job.GetDescription() );
|
|
|
|
|
|
|
|
num++;
|
2024-07-15 18:20:13 -04:00
|
|
|
}
|
|
|
|
|
2024-12-29 07:16:38 -05:00
|
|
|
UpdateTitle();
|
2024-12-26 11:24:32 -05:00
|
|
|
|
|
|
|
// Ensure the outputs get their Run-ability status updated
|
2025-01-12 10:54:45 +00:00
|
|
|
for( PANEL_JOB_OUTPUT* panel : GetOutputPanels() )
|
|
|
|
panel->UpdateStatus();
|
2024-07-15 18:20:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-12-29 07:16:38 -05:00
|
|
|
void PANEL_JOBS::UpdateTitle()
|
2024-07-15 18:20:13 -04:00
|
|
|
{
|
|
|
|
wxString tabName = m_jobsFile->GetFullName();
|
2024-12-30 21:12:41 +00:00
|
|
|
|
2024-07-15 18:20:13 -04:00
|
|
|
if( m_jobsFile->GetDirty() )
|
|
|
|
tabName = wxS( "*" ) + tabName;
|
2024-12-30 21:12:41 +00:00
|
|
|
|
2024-07-15 18:20:13 -04:00
|
|
|
int pageIdx = m_parentBook->FindPage( this );
|
|
|
|
m_parentBook->SetPageText( pageIdx, tabName );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PANEL_JOBS::addJobOutputPanel( JOBSET_OUTPUT* aOutput )
|
|
|
|
{
|
2024-12-30 18:23:34 +00:00
|
|
|
PANEL_JOB_OUTPUT* outputPanel = new PANEL_JOB_OUTPUT( m_outputList, this, m_frame,
|
|
|
|
m_jobsFile.get(), aOutput );
|
2025-01-04 13:23:49 +00:00
|
|
|
|
|
|
|
#if __OSX__
|
2024-12-30 18:23:34 +00:00
|
|
|
m_outputListSizer->Add( outputPanel, 0, wxEXPAND, 5 );
|
2025-01-04 13:23:49 +00:00
|
|
|
#else
|
2025-01-04 13:41:31 +00:00
|
|
|
m_outputListSizer->Add( outputPanel, 0, wxEXPAND|wxLEFT|wxRIGHT|wxBOTTOM, 5 );
|
2025-01-04 13:23:49 +00:00
|
|
|
#endif
|
2024-07-15 18:20:13 -04:00
|
|
|
|
|
|
|
m_outputList->Layout();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2025-01-12 10:54:45 +00:00
|
|
|
std::vector<PANEL_JOB_OUTPUT*> PANEL_JOBS::GetOutputPanels()
|
|
|
|
{
|
|
|
|
std::vector<PANEL_JOB_OUTPUT*> panels;
|
|
|
|
|
|
|
|
for( const wxSizerItem* item : m_outputListSizer->GetChildren() )
|
|
|
|
{
|
|
|
|
if( PANEL_JOB_OUTPUT* panel = dynamic_cast<PANEL_JOB_OUTPUT*>( item->GetWindow() ) )
|
|
|
|
panels.push_back( panel );
|
|
|
|
}
|
|
|
|
|
|
|
|
return panels;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-15 18:20:13 -04:00
|
|
|
void PANEL_JOBS::buildOutputList()
|
|
|
|
{
|
|
|
|
Freeze();
|
|
|
|
|
2024-12-30 18:23:34 +00:00
|
|
|
for( JOBSET_OUTPUT& job : m_jobsFile->GetOutputs() )
|
2024-07-15 18:20:13 -04:00
|
|
|
addJobOutputPanel( &job );
|
|
|
|
|
|
|
|
// ensure the window contents get shifted as needed
|
|
|
|
Layout();
|
|
|
|
Thaw();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2025-01-01 19:15:33 +00:00
|
|
|
bool PANEL_JOBS::OpenJobOptionsForListItem( size_t aItemIndex )
|
2024-07-15 18:20:13 -04:00
|
|
|
{
|
2024-10-03 08:02:21 -04:00
|
|
|
JOBSET_JOB& job = m_jobsFile->GetJobs()[aItemIndex];
|
2024-07-15 18:20:13 -04:00
|
|
|
|
|
|
|
KIWAY::FACE_T iface = JOB_REGISTRY::GetKifaceType( job.m_type );
|
|
|
|
|
2024-10-22 22:29:14 -04:00
|
|
|
if( iface < KIWAY::KIWAY_FACE_COUNT )
|
|
|
|
{
|
|
|
|
EnsurePcbSchFramesOpen();
|
|
|
|
|
2025-01-01 19:15:33 +00:00
|
|
|
if( m_frame->Kiway().ProcessJobConfigDialog( iface, job.m_job.get(), m_frame ) )
|
2024-12-27 20:15:27 -05:00
|
|
|
{
|
|
|
|
m_jobsFile->SetDirty();
|
2024-12-29 07:16:38 -05:00
|
|
|
UpdateTitle();
|
2025-01-01 19:15:33 +00:00
|
|
|
return true;
|
2024-12-27 20:15:27 -05:00
|
|
|
}
|
|
|
|
}
|
2024-10-22 22:29:14 -04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// special jobs
|
|
|
|
if( job.m_job->GetType() == "special_execute" )
|
|
|
|
{
|
2024-11-09 22:49:54 -05:00
|
|
|
JOB_SPECIAL_EXECUTE* specialJob = static_cast<JOB_SPECIAL_EXECUTE*>( job.m_job.get() );
|
2024-10-22 22:29:14 -04:00
|
|
|
|
2025-01-04 13:06:09 +00:00
|
|
|
DIALOG_EXECUTECOMMAND_JOB_SETTINGS dialog( m_frame, specialJob );
|
|
|
|
|
2025-01-01 14:52:39 -05:00
|
|
|
if( dialog.ShowModal() == wxID_OK )
|
|
|
|
{
|
|
|
|
m_jobsFile->SetDirty();
|
|
|
|
UpdateTitle();
|
|
|
|
return true;
|
|
|
|
}
|
2024-10-22 22:29:14 -04:00
|
|
|
}
|
2025-01-01 23:57:14 -05:00
|
|
|
else if( job.m_job->GetType() == "special_copyfiles" )
|
|
|
|
{
|
|
|
|
JOB_SPECIAL_COPYFILES* specialJob =
|
|
|
|
static_cast<JOB_SPECIAL_COPYFILES*>( job.m_job.get() );
|
2025-01-04 13:06:09 +00:00
|
|
|
DIALOG_COPYFILES_JOB_SETTINGS dialog( m_frame, specialJob );
|
|
|
|
|
2025-01-01 23:57:14 -05:00
|
|
|
if( dialog.ShowModal() == wxID_OK )
|
|
|
|
{
|
|
|
|
m_jobsFile->SetDirty();
|
|
|
|
UpdateTitle();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2024-10-22 22:29:14 -04:00
|
|
|
}
|
2025-01-01 19:15:33 +00:00
|
|
|
|
|
|
|
return false;
|
2024-07-15 18:20:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2025-01-06 19:10:42 +00:00
|
|
|
void PANEL_JOBS::OnGridCellChange( wxGridEvent& aEvent )
|
|
|
|
{
|
|
|
|
int row = aEvent.GetRow();
|
|
|
|
int col = aEvent.GetCol();
|
|
|
|
|
|
|
|
if( col == 1 )
|
|
|
|
m_jobsFile->GetJobs()[row].SetDescription( m_jobsGrid->GetCellValue( row, col ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-15 18:20:13 -04:00
|
|
|
void PANEL_JOBS::OnSaveButtonClick( wxCommandEvent& aEvent )
|
|
|
|
{
|
2025-01-06 19:10:42 +00:00
|
|
|
if( !m_jobsGrid->CommitPendingChanges() )
|
|
|
|
return;
|
|
|
|
|
2024-12-27 20:15:27 -05:00
|
|
|
m_jobsFile->SaveToFile( wxEmptyString, true );
|
2024-12-29 07:16:38 -05:00
|
|
|
UpdateTitle();
|
2024-07-15 18:20:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PANEL_JOBS::OnAddJobClick( wxCommandEvent& aEvent )
|
|
|
|
{
|
2025-01-06 19:10:42 +00:00
|
|
|
if( !m_jobsGrid->CommitPendingChanges() )
|
|
|
|
return;
|
|
|
|
|
2024-07-15 18:20:13 -04:00
|
|
|
wxArrayString headers;
|
|
|
|
std::vector<wxArrayString> items;
|
|
|
|
|
|
|
|
headers.Add( _( "Job Types" ) );
|
|
|
|
|
|
|
|
const JOB_REGISTRY::REGISTRY_MAP_T& jobMap = JOB_REGISTRY::GetRegistry();
|
|
|
|
|
2024-10-01 18:38:41 +02:00
|
|
|
for( const std::pair<const wxString, JOB_REGISTRY_ENTRY>& entry : jobMap )
|
2024-07-15 18:20:13 -04:00
|
|
|
{
|
|
|
|
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() )
|
|
|
|
{
|
2024-10-01 18:38:41 +02:00
|
|
|
for( const std::pair<const wxString, JOB_REGISTRY_ENTRY>& entry : jobMap )
|
2024-07-15 18:20:13 -04:00
|
|
|
{
|
|
|
|
if( wxGetTranslation( entry.second.title ) == selectedString )
|
|
|
|
{
|
|
|
|
jobKey = entry.first;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !jobKey.IsEmpty() )
|
|
|
|
{
|
2025-01-01 19:15:33 +00:00
|
|
|
int row = m_jobsFile->GetJobs().size();
|
|
|
|
bool wasDirty = m_jobsFile->GetDirty();
|
2024-07-15 18:20:13 -04:00
|
|
|
JOB* job = JOB_REGISTRY::CreateInstance<JOB>( jobKey );
|
2025-01-01 19:15:33 +00:00
|
|
|
|
2024-07-15 18:20:13 -04:00
|
|
|
m_jobsFile->AddNewJob( jobKey, job );
|
|
|
|
|
2025-01-01 19:15:33 +00:00
|
|
|
if( OpenJobOptionsForListItem( row ) )
|
|
|
|
{
|
|
|
|
rebuildJobList();
|
|
|
|
|
|
|
|
m_jobsGrid->SetGridCursor( row, 1 );
|
|
|
|
m_jobsGrid->EnableCellEditControl();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_jobsFile->RemoveJob( row );
|
|
|
|
m_jobsFile->SetDirty( wasDirty );
|
|
|
|
}
|
2024-07-15 18:20:13 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2025-01-06 19:10:42 +00:00
|
|
|
void PANEL_JOBS::OnJobButtonDelete( wxCommandEvent& aEvent )
|
|
|
|
{
|
|
|
|
if( !m_jobsGrid->CommitPendingChanges() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
wxArrayInt selectedRows = m_jobsGrid->GetSelectedRows();
|
|
|
|
|
|
|
|
if( selectedRows.empty() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_jobsGrid->CommitPendingChanges( true /* quiet mode */ );
|
|
|
|
m_jobsGrid->ClearSelection();
|
|
|
|
|
|
|
|
// Reverse sort so deleting a row doesn't change the indexes of the other rows.
|
|
|
|
selectedRows.Sort( []( int* first, int* second ) { return *second - *first; } );
|
|
|
|
|
|
|
|
int select = selectedRows[0];
|
|
|
|
|
|
|
|
for( int row : selectedRows )
|
|
|
|
m_jobsFile->RemoveJob( row );
|
|
|
|
|
|
|
|
rebuildJobList();
|
|
|
|
|
|
|
|
if( m_jobsGrid->GetNumberRows() )
|
|
|
|
{
|
|
|
|
m_jobsGrid->MakeCellVisible( std::max( 0, select-1 ), m_jobsGrid->GetGridCursorCol() );
|
|
|
|
m_jobsGrid->SetGridCursor( std::max( 0, select-1 ), m_jobsGrid->GetGridCursorCol() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-15 18:20:13 -04:00
|
|
|
void PANEL_JOBS::OnAddOutputClick( wxCommandEvent& aEvent )
|
|
|
|
{
|
|
|
|
wxArrayString headers;
|
|
|
|
std::vector<wxArrayString> items;
|
|
|
|
|
2024-12-29 07:16:38 -05:00
|
|
|
headers.Add( _( "Output Types" ) );
|
2024-07-15 18:20:13 -04:00
|
|
|
|
2025-01-12 12:11:56 +00:00
|
|
|
for( const std::pair<const JOBSET_OUTPUT_TYPE, JOBSET_OUTPUT_TYPE_INFO>& outputType : JobsetOutputTypeInfos )
|
2024-07-15 18:20:13 -04:00
|
|
|
{
|
|
|
|
wxArrayString item;
|
2024-12-29 07:16:38 -05:00
|
|
|
item.Add( wxGetTranslation( outputType.second.name ) );
|
2024-07-15 18:20:13 -04:00
|
|
|
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();
|
|
|
|
|
2025-01-12 12:11:56 +00:00
|
|
|
for( const std::pair<const JOBSET_OUTPUT_TYPE, JOBSET_OUTPUT_TYPE_INFO>& jobType : JobsetOutputTypeInfos )
|
2024-07-15 18:20:13 -04:00
|
|
|
{
|
|
|
|
if( wxGetTranslation( jobType.second.name ) == selectedString )
|
|
|
|
{
|
2024-12-20 22:39:51 -05:00
|
|
|
JOBSET_OUTPUT* output = m_jobsFile->AddNewJobOutput( jobType.first );
|
2024-07-15 18:20:13 -04:00
|
|
|
|
2025-01-12 12:11:56 +00:00
|
|
|
DIALOG_JOB_OUTPUT_OPTIONS dialog( m_frame, m_jobsFile.get(), output );
|
2025-01-01 14:52:39 -05:00
|
|
|
if (dialog.ShowModal() == wxID_OK)
|
2024-12-21 16:12:04 -05:00
|
|
|
{
|
|
|
|
Freeze();
|
|
|
|
addJobOutputPanel( output );
|
|
|
|
m_buttonRunAllOutputs->Enable( !m_jobsFile->GetOutputs().empty() );
|
|
|
|
Thaw();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// canceled
|
|
|
|
m_jobsFile->RemoveOutput( output );
|
|
|
|
}
|
2024-07-15 18:20:13 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
{
|
2025-01-06 12:41:46 +01:00
|
|
|
return m_jobsFile->SaveToFile(wxEmptyString, true);
|
2024-07-15 18:20:13 -04:00
|
|
|
} ) )
|
|
|
|
{
|
|
|
|
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 );
|
|
|
|
|
2024-12-20 11:22:41 -08:00
|
|
|
// Prevent our window from being closed during the open process
|
|
|
|
wxEventBlocker blocker( this );
|
|
|
|
|
2024-07-15 18:20:13 -04:00
|
|
|
frame->OpenProjectFiles( std::vector<wxString>( 1, boardfn.GetFullPath() ) );
|
2025-01-04 18:17:53 -05:00
|
|
|
|
|
|
|
if( !frame->IsVisible() )
|
|
|
|
frame->Show( true );
|
2024-07-15 18:20:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
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 );
|
|
|
|
|
2024-12-20 11:22:41 -08:00
|
|
|
wxEventBlocker blocker( this );
|
|
|
|
|
2024-07-15 18:20:13 -04:00
|
|
|
frame->OpenProjectFiles( std::vector<wxString>( 1, schFn.GetFullPath() ) );
|
2025-01-04 18:17:53 -05:00
|
|
|
|
|
|
|
if( !frame->IsVisible() )
|
|
|
|
frame->Show( true );
|
2024-07-15 18:20:13 -04:00
|
|
|
}
|
2025-01-04 18:17:53 -05:00
|
|
|
|
|
|
|
SetFocus();
|
2024-10-01 14:11:28 -04:00
|
|
|
}
|
2024-10-02 22:53:43 -04:00
|
|
|
|
|
|
|
|
2024-12-21 12:02:21 -05:00
|
|
|
wxString PANEL_JOBS::GetFilePath() const
|
|
|
|
{
|
|
|
|
return m_jobsFile->GetFullFilename();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-10-02 22:53:43 -04:00
|
|
|
void PANEL_JOBS::OnJobButtonUp( wxCommandEvent& aEvent )
|
|
|
|
{
|
2024-12-30 18:23:34 +00:00
|
|
|
if( !m_jobsGrid->CommitPendingChanges() )
|
2024-10-02 22:53:43 -04:00
|
|
|
return;
|
|
|
|
|
2024-12-30 18:23:34 +00:00
|
|
|
int item = m_jobsGrid->GetGridCursorRow();
|
2024-10-02 22:53:43 -04:00
|
|
|
|
2024-12-30 18:23:34 +00:00
|
|
|
if( item > 0 )
|
|
|
|
{
|
|
|
|
m_jobsFile->MoveJobUp( item );
|
2024-10-02 22:53:43 -04:00
|
|
|
|
2024-12-30 18:23:34 +00:00
|
|
|
rebuildJobList();
|
2024-10-02 22:53:43 -04:00
|
|
|
|
2024-12-30 18:23:34 +00:00
|
|
|
m_jobsGrid->SelectRow( item - 1 );
|
2025-01-07 23:31:19 +00:00
|
|
|
m_jobsGrid->SetGridCursor( item - 1, m_jobsGrid->GetGridCursorCol() );
|
2024-12-30 18:23:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wxBell();
|
|
|
|
}
|
2024-10-02 22:53:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PANEL_JOBS::OnJobButtonDown( wxCommandEvent& aEvent )
|
|
|
|
{
|
2024-12-30 18:23:34 +00:00
|
|
|
if( !m_jobsGrid->CommitPendingChanges() )
|
2024-10-02 22:53:43 -04:00
|
|
|
return;
|
|
|
|
|
2024-12-30 18:23:34 +00:00
|
|
|
int item = m_jobsGrid->GetGridCursorRow();
|
|
|
|
|
|
|
|
if( item < m_jobsGrid->GetNumberRows() - 1 )
|
|
|
|
{
|
|
|
|
m_jobsFile->MoveJobDown( item );
|
|
|
|
|
|
|
|
rebuildJobList();
|
|
|
|
|
|
|
|
m_jobsGrid->SelectRow( item + 1 );
|
2025-01-07 23:31:19 +00:00
|
|
|
m_jobsGrid->SetGridCursor( item + 1, m_jobsGrid->GetGridCursorCol() );
|
2024-12-30 18:23:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wxBell();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2025-01-06 19:10:42 +00:00
|
|
|
void PANEL_JOBS::OnRunAllJobsClick( wxCommandEvent& event )
|
2024-12-30 18:23:34 +00:00
|
|
|
{
|
2025-01-06 19:10:42 +00:00
|
|
|
if( !m_jobsGrid->CommitPendingChanges() )
|
2024-10-02 22:53:43 -04:00
|
|
|
return;
|
|
|
|
|
2024-11-07 07:25:40 -05:00
|
|
|
// sanity
|
|
|
|
if( m_jobsFile->GetOutputs().empty() )
|
|
|
|
{
|
|
|
|
DisplayError( this, _( "No outputs defined" ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CallAfter(
|
|
|
|
[this]()
|
|
|
|
{
|
|
|
|
PROJECT& project = m_frame->Kiway().Prj();
|
|
|
|
EnsurePcbSchFramesOpen();
|
|
|
|
|
|
|
|
wxFileName fn = project.GetProjectFullName();
|
|
|
|
wxSetWorkingDirectory( fn.GetPath() );
|
|
|
|
|
2024-12-24 11:44:22 -05:00
|
|
|
JOBS_RUNNER jobRunner( &( m_frame->Kiway() ), m_jobsFile.get(), &project );
|
2024-11-07 07:25:40 -05:00
|
|
|
|
|
|
|
WX_PROGRESS_REPORTER* progressReporter =
|
|
|
|
new WX_PROGRESS_REPORTER( m_frame, _( "Running jobs" ), 1 );
|
|
|
|
|
|
|
|
jobRunner.RunJobsAllOutputs();
|
|
|
|
|
2025-01-12 10:54:45 +00:00
|
|
|
for( PANEL_JOB_OUTPUT* panel : GetOutputPanels() )
|
2024-12-16 22:32:22 -05:00
|
|
|
panel->UpdateStatus();
|
|
|
|
|
2024-11-07 07:25:40 -05:00
|
|
|
delete progressReporter;
|
2025-01-12 10:58:43 +00:00
|
|
|
|
|
|
|
// Bring the Kicad manager frame back to the front
|
|
|
|
m_frame->Raise();
|
2024-11-07 07:25:40 -05:00
|
|
|
} );
|
2024-12-30 18:23:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PANEL_JOBS::OnSizeGrid( wxSizeEvent& aEvent )
|
|
|
|
{
|
2024-12-31 10:37:44 +00:00
|
|
|
m_jobsGrid->SetColSize( 1, m_jobsGrid->GetSize().x - m_jobsGrid->GetColSize( 0 ) );
|
2024-12-30 18:23:34 +00:00
|
|
|
|
|
|
|
// Always propagate for a grid repaint (needed if the height changes, as well as width)
|
|
|
|
aEvent.Skip();
|
|
|
|
}
|
|
|
|
|