KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_executecommand_job_settings.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2024 Mark Roszko <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
24#include <scintilla_tricks.h>
25#include <grid_tricks.h>
26#include <project.h>
27#include <env_vars.h>
28#include <common.h>
29#include <wx/regex.h>
30
31
33 PROJECT* aProject ) :
35 m_job( aJob ),
36 m_project( aProject ),
37 m_lastFocusedInput( nullptr ),
38 m_scintillaTricks( nullptr )
39{
40 m_textCtrlCommand->SetWrapMode( wxSTC_WRAP_CHAR );
41
42 m_scintillaTricks = new SCINTILLA_TRICKS( m_textCtrlCommand, wxT( "{}" ), false,
43 // onAcceptFn
44 [this]( wxKeyEvent& aEvent )
45 {
46 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
47 },
48
49 // onCharFn
50 [this]( wxStyledTextEvent& aEvent )
51 {
52 m_scintillaTricks->DoTextVarAutocomplete(
53 // getTokensFn
54 []( const wxString& xRef, wxArrayString* tokens )
55 {
57 tokens->Add( OUTPUT_TMP_PATH_VAR_NAME );
58 } );
59 } );
60
61 // add Cut, Copy, and Paste to wxGrids
62 m_path_subs_grid->PushEventHandler( new GRID_TRICKS( m_path_subs_grid ) );
63
65
67
68 m_textCtrlCommand->Bind( wxEVT_SET_FOCUS,
69 [this]( wxFocusEvent& aEvent )
70 {
72 aEvent.Skip();
73 } );
74
75 m_textCtrlOutputPath->Bind( wxEVT_SET_FOCUS,
76 [this]( wxFocusEvent& aEvent )
77 {
79 aEvent.Skip();
80 } );
81
82 m_path_subs_grid->Bind( wxEVT_GRID_CELL_LEFT_DCLICK, &DIALOG_EXECUTECOMMAND_JOB_SETTINGS::onVarGridDClick, this );
83
85
86 // keep the grid at 10 rows, it scrolls for more
87 m_path_subs_grid->SetMinSize( wxSize( -1, m_path_subs_grid->GetDefaultRowSize() * 10 ) );
88
89 m_path_subs_grid->SetColLabelValue( 0, _( "Name" ) );
90 m_path_subs_grid->SetColLabelValue( 1, _( "Value" ) );
91
93
95}
96
97
99{
100 delete m_scintillaTricks;
101 m_scintillaTricks = nullptr;
102
103 // Delete the GRID_TRICKS.
104 m_path_subs_grid->PopEventHandler( true );
105}
106
107
109{
110 m_job->m_command = m_textCtrlCommand->GetValue();
111 m_job->m_ignoreExitcode = m_cbIgnoreExitCode->GetValue();
112 m_job->m_recordOutput = m_cbRecordOutput->GetValue();
113 m_job->SetConfiguredOutputPath( m_textCtrlOutputPath->GetValue() );
114
115 return true;
116}
117
118
120{
121 m_textCtrlCommand->SetValue( m_job->m_command );
122 m_cbIgnoreExitCode->SetValue( m_job->m_ignoreExitcode );
123 m_cbRecordOutput->SetValue( m_job->m_recordOutput );
124
125 m_textCtrlOutputPath->SetValue( m_job->GetConfiguredOutputPath() );
126 m_textCtrlOutputPath->Enable( m_cbRecordOutput->GetValue() );
127
129
130 return true;
131}
132
133
135{
136 m_textCtrlOutputPath->Enable( m_cbRecordOutput->GetValue() );
137}
138
139
141{
143 aEvent.Skip();
144}
145
146
148{
149 int row = aEvent.GetRow();
150
151 if( row < 0 || row >= m_path_subs_grid->GetNumberRows() )
152 return;
153
154 wxString token = m_path_subs_grid->GetCellValue( row, 0 );
155
157 m_textCtrlOutputPath->WriteText( token );
158 else
159 m_textCtrlCommand->ReplaceSelection( token );
160}
161
162
164{
165 wxRegEx re( ".*?(\\$\\{(.+?)\\})|(\\$\\((.+?)\\)).*?", wxRE_ADVANCED );
166 wxASSERT( re.IsValid() ); // wxRE_ADVANCED is required.
167
168 std::set<wxString> unique;
169 wxString src = m_textCtrlCommand->GetValue();
170
171 // clear the table
172 m_path_subs_grid->ClearRows();
173
174 // all configured path and environment variables
175 wxArrayString envTokens;
177
178 for( const wxString& token : envTokens )
179 unique.insert( token );
180
181 // project text variables
182 if( m_project )
183 {
184 for( const auto& [varName, varValue] : m_project->GetTextVars() )
185 unique.insert( varName );
186 }
187
188 // variables referenced in the command, including undefined ones
189 while( re.Matches( src ) )
190 {
191 wxString envvar = re.GetMatch( src, 2 );
192
193 // if not ${...} form then must be $(...)
194 if( envvar.IsEmpty() )
195 envvar = re.GetMatch( src, 4 );
196
197 // ignore duplicates
198 unique.insert( envvar );
199
200 // delete the last match and search again
201 src.Replace( re.GetMatch( src, 0 ), wxEmptyString );
202 }
203
204 // Make sure these variables shows up even if not used yet.
205 unique.insert( OUTPUT_TMP_PATH_VAR_NAME );
206 unique.insert( PROJECT_VAR_NAME );
207
208 for( const wxString& evName : unique )
209 {
210 int row = m_path_subs_grid->GetNumberRows();
211 m_path_subs_grid->AppendRows( 1 );
212
213 m_path_subs_grid->SetCellValue( row, 0, wxT( "${" ) + evName + wxT( "}" ) );
214 m_path_subs_grid->SetCellEditor( row, 0, new GRID_CELL_READONLY_TEXT_EDITOR() );
215
216 wxString evValue;
217
218 if( evName.IsSameAs( OUTPUT_TMP_PATH_VAR_NAME ) )
219 {
220 evValue = _( "<value set at runtime>" );
221 m_path_subs_grid->SetCellFont( row, 1, m_path_subs_grid->GetCellFont( row, 1 ).Italic() );
222 }
223 else
224 {
225 // resolve the same way the job runner will
226 wxString token = wxT( "${" ) + evName + wxT( "}" );
227 evValue = ExpandEnvVarSubstitutions( token, m_project );
228
229 if( evValue == token )
230 evValue = wxEmptyString;
231 }
232
233 m_path_subs_grid->SetCellValue( row, 1, evValue );
234 m_path_subs_grid->SetCellEditor( row, 1, new GRID_CELL_READONLY_TEXT_EDITOR() );
235 }
236
237 adjustPathSubsGridColumns( m_path_subs_grid->GetRect().GetWidth() );
238}
239
240
242{
243 // Account for scroll bars
244 aWidth -= ( m_path_subs_grid->GetSize().x - m_path_subs_grid->GetClientSize().x );
245
246 m_path_subs_grid->AutoSizeColumn( 0 );
247 m_path_subs_grid->SetColSize( 0, std::max( 200, m_path_subs_grid->GetColSize( 0 ) ) );
248 m_path_subs_grid->SetColSize( 1, std::max( 300, aWidth - m_path_subs_grid->GetColSize( 0 ) ) );
249}
250
251
253{
254 adjustPathSubsGridColumns( event.GetSize().GetX() );
255
256 event.Skip();
257}
258
259
DIALOG_EXECUTECOMMAND_JOB_SETTINGS_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Execute Command Job Settings"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
DIALOG_EXECUTECOMMAND_JOB_SETTINGS(wxWindow *aParent, JOB_SPECIAL_EXECUTE *aJob, PROJECT *aProject)
void populateEnvironReadOnlyTable()
Fill the variable table with the available variables and any referenced in the command,...
void OnRecordOutputClicked(wxCommandEvent &event) override
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
Add mouse and command handling (such as cut, copy, and paste) to a WX_GRID instance.
Definition grid_tricks.h:57
Container for project specific data.
Definition project.h:63
Add cut/copy/paste, dark theme, autocomplete and brace highlighting to a wxStyleTextCtrl instance.
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition common.cpp:721
The common library.
#define _(s)
Functions related to environment variables, including help functions.
#define OUTPUT_TMP_PATH_VAR_NAME
KICOMMON_API void GetEnvVarAutocompleteTokens(wxArrayString *aVars)
Return autocomplete tokens for environment variables for Scintilla.
Definition env_vars.cpp:68
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
Definition project.h:38