KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_destination.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
21#include "dialog_destination.h"
23#include <wx/aui/auibook.h>
24#include <jobs/jobset.h>
25#include <jobs/job_registry.h>
26#include <wx/checkbox.h>
27#include <wx/menu.h>
28#include <bitmaps.h>
30#include <kicad_manager_frame.h>
31#include <vector>
32
33#include <wx/dirdlg.h>
34#include <wx/filedlg.h>
35#include <kiplatform/ui.h>
38#include <widgets/wx_grid.h>
41#include <confirm.h>
42#include <env_paths.h>
43#include <common.h>
44#include <pgm_base.h>
45
46
47extern KICOMMON_API
48std::map<JOBSET_DESTINATION_T, JOBSET_DESTINATION_T_INFO> JobsetDestinationTypeInfos;
49
50
51DIALOG_DESTINATION::DIALOG_DESTINATION( wxWindow* aParent, JOBSET* aJobsFile,
52 JOBSET_DESTINATION* aDestination ) :
53 DIALOG_DESTINATION_BASE( aParent ),
54 m_jobsFile( aJobsFile ),
55 m_destination( aDestination )
56{
57 // prevent someone from failing to add the type info in the future
58 wxASSERT( JobsetDestinationTypeInfos.contains( m_destination->m_type ) );
59
60 SetTitle( wxString::Format( _( "%s Destination" ),
61 m_destination->m_outputHandler->GetDefaultDescription() ) );
62
63 if( m_destination->m_type != JOBSET_DESTINATION_T::ARCHIVE )
64 {
65 m_textArchiveFormat->Hide();
67 }
68
70
71 m_buttonDeselectAll->Connect( wxEVT_COMMAND_BUTTON_CLICKED,
72 wxCommandEventHandler( DIALOG_DESTINATION::onDeselectAllClicked ),
73 NULL, this );
74
75 m_includeJobs->Connect( wxEVT_CHECKLISTBOX,
76 wxCommandEventHandler( DIALOG_DESTINATION::onIncludeJobsCheck ),
77 NULL, this );
78
80}
81
82
84{
85 bool isFolder = false;
86 wxString fileWildcard = "";
87 isFolder = JobsetDestinationTypeInfos[m_destination->m_type].outputPathIsFolder;
88 fileWildcard = JobsetDestinationTypeInfos[m_destination->m_type].fileWildcard;
89
90 // The GUI runs jobs from the project directory, so that is where relative paths resolve
91 wxString projectPath = Prj().GetProjectPath();
92
93 // Expand the same way JOBS_OUTPUT_FOLDER and JOBS_OUTPUT_ARCHIVE do so the picker opens where output lands
94 wxString current = ExpandTextVars( m_textCtrlOutputPath->GetValue(), &Prj(), INTERNAL );
95 current = ExpandEnvVarSubstitutions( current, &Prj() );
96
97 if( isFolder )
98 {
99 wxFileName fn;
100 fn.AssignDir( current );
101 fn.Normalize( FN_NORMALIZE_FLAGS, projectPath );
102 wxString currPath = fn.GetFullPath();
103
104 wxDirDialog dirDialog( this, _( "Select output directory" ), currPath,
105 wxDD_DEFAULT_STYLE );
106
107 if( dirDialog.ShowModal() != wxID_OK )
108 return;
109
110 wxString path = wxFileName::DirName( dirDialog.GetPath() ).GetFullPath();
111 wxString shortPath = NormalizePathForProject( path, &Pgm().GetLocalEnvVariables(), projectPath, false );
112 wxString parentPath = MakeRelativePath( path, projectPath );
113
114 // wxDirDialog cannot host a customize hook, so ask before leaving the project with ".."
115 if( shortPath == path && parentPath != path
116 && IsOK( this, wxString::Format( _( "Do you want to use a path relative to\n'%s'?" ), projectPath ) ) )
117 {
118 shortPath = parentPath;
119 }
120
121 m_textCtrlOutputPath->SetValue( shortPath );
122 }
123 else
124 {
125 wxFileName fname( current );
126 fname.MakeAbsolute( projectPath );
127
129 wxFileDialog dlg( this, _( "Select output path" ), fname.GetPath(), fname.GetFullName(),
130 fileWildcard,
131 wxFD_OVERWRITE_PROMPT | wxFD_SAVE );
132
133 if( !projectPath.IsEmpty() )
134 dlg.SetCustomizeHook( customize );
135
137
138 if( dlg.ShowModal() != wxID_OK )
139 return;
140
141 wxString path = dlg.GetPath();
142
143 if( m_destination->m_type == JOBSET_DESTINATION_T::ARCHIVE )
144 {
145 wxFileName fn( path );
146
147 if( fn.GetExt().IsEmpty() )
149
150 path = fn.GetFullPath();
151 }
152
153 path = NormalizePathForProject( path, &Pgm().GetLocalEnvVariables(), projectPath,
154 !projectPath.IsEmpty() && customize.GetUseRelativePath() );
155
156 m_textCtrlOutputPath->SetValue( path );
157 }
158
159}
160
161
163{
164 for( size_t idx = 0; idx < m_includeJobs->GetCount(); ++idx )
165 {
166 m_includeJobs->Check( idx, false );
167 }
168
169 event.Skip();
170}
171
172
173void DIALOG_DESTINATION::onIncludeJobsCheck(wxCommandEvent& event)
174{
175 int clickedIndex = event.GetInt();
176
177 bool newCheckedState = m_includeJobs->IsChecked( clickedIndex );
178
179 wxArrayInt currentSelections;
180 m_includeJobs->GetSelections( currentSelections );
181
182 for( size_t i = 0; i < currentSelections.GetCount(); i++ )
183 {
184 m_includeJobs->Check( currentSelections[i], newCheckedState );
185 }
186
187 event.Skip();
188}
189
190
192{
193 wxString outputPath = m_textCtrlOutputPath->GetValue().Trim().Trim( false );
194
195 if( outputPath.IsEmpty() )
196 {
197 DisplayErrorMessage( this, _( "Output path cannot be empty" ) );
198 return false;
199 }
200
201 wxArrayInt selectedItems;
202 m_includeJobs->GetCheckedItems( selectedItems );
203
204 // Update the only job map
205 m_destination->m_only.clear();
206
207 if( selectedItems.size() < m_includeJobs->GetCount() )
208 {
209 for( int i : selectedItems )
210 {
211 if( m_onlyMap.contains( i ) )
212 m_destination->m_only.emplace_back( m_onlyMap[i] );
213 }
214 }
215
216 m_destination->m_outputHandler->SetOutputPath( outputPath );
217
218 if( m_destination->m_type == JOBSET_DESTINATION_T::ARCHIVE )
219 {
220 JOBS_OUTPUT_ARCHIVE* archive =
221 static_cast<JOBS_OUTPUT_ARCHIVE*>( m_destination->m_outputHandler.get() );
222
224 }
225
226 m_destination->SetDescription( m_textCtrlDescription->GetValue() );
227
228 return true;
229}
230
231
233{
234 m_textCtrlDescription->SetValue( m_destination->GetDescription() );
235 m_textCtrlOutputPath->SetValue( m_destination->m_outputHandler->GetOutputPath() );
236
237 wxArrayString arrayStr;
238 std::vector<int> selectedList;
239
240 for( JOBSET_JOB& job : m_jobsFile->GetJobs() )
241 {
242 arrayStr.Add( wxString::Format( wxT( "%d. %s" ),
243 (int) arrayStr.size() + 1,
244 job.GetDescription() ) );
245
246 auto it = std::find_if( m_destination->m_only.begin(), m_destination->m_only.end(),
247 [&]( const wxString& only )
248 {
249 if( only == job.m_id )
250 return true;
251
252 return false;
253 } );
254
255 if( it != m_destination->m_only.end() )
256 selectedList.emplace_back( arrayStr.size() - 1 );
257
258 m_onlyMap.emplace( arrayStr.size() - 1, job.m_id );
259 }
260
261 if( arrayStr.size() != 0 )
262 {
263 m_includeJobs->InsertItems( arrayStr, 0 );
264
265 if( selectedList.size() )
266 {
267 for( int idx : selectedList )
268 m_includeJobs->Check( idx );
269 }
270 else
271 {
272 for( size_t idx = 0; idx < m_includeJobs->GetCount(); ++idx )
273 m_includeJobs->Check( idx );
274 }
275 }
276
277 m_choiceArchiveformat->AppendString( _( "Zip" ) );
278 m_choiceArchiveformat->SetSelection( 0 );
279
280 return true;
281}
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:106
STD_BITMAP_BUTTON * m_buttonOutputPath
DIALOG_DESTINATION_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("%s Destination"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
DIALOG_DESTINATION(wxWindow *aParent, JOBSET *aJobsFile, JOBSET_DESTINATION *aDestination)
std::map< int, wxString > m_onlyMap
bool TransferDataToWindow() override
void onIncludeJobsCheck(wxCommandEvent &event)
bool TransferDataFromWindow() override
virtual void onOutputPathBrowseClicked(wxCommandEvent &event) override
void onDeselectAllClicked(wxCommandEvent &event)
JOBSET_DESTINATION * m_destination
void SetupStandardButtons(std::map< int, wxString > aLabels={})
Add a sticky "Use relative path" checkbox to a file dialog.
void SetFormat(FORMAT format)
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:276
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject, bool aAllowEscapes)
Replace any environment variable & text variable references with their values.
Definition common.cpp:777
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, RESOLUTION_CONTEXT aContext)
Definition common.cpp:60
@ INTERNAL
Definition common.h:96
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
Definition confirm.cpp:274
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:217
This file is part of the common library.
#define _(s)
wxString MakeRelativePath(const wxString &aPath, const wxString &aBaseDir)
Express an absolute path relative to a base directory, stepping out with ".." when needed.
wxString NormalizePathForProject(const wxString &aPath, const ENV_VAR_MAP *aEnvVars, const wxString &aProjectPath, bool aAllowParentDirs)
Choose how to store a path the user picked for a project.
Helper functions to substitute paths with environmental variables.
static const std::string ArchiveFileExtension
KICOMMON_API std::map< JOBSET_DESTINATION_T, JOBSET_DESTINATION_T_INFO > JobsetDestinationTypeInfos
Definition jobset.cpp:43
#define KICOMMON_API
Definition kicommon.h:27
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:640
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
std::string path
Definition of file extensions used in Kicad.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition wx_filename.h:35