1 /**
2  * @file dialog_config_equfiles.cpp
3  */
4 
5 /*
6  * This program source code file is part of KiCad, a free EDA CAD application.
7  *
8  * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
9  * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, you may find one here:
23  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
24  * or you may search the http://www.gnu.org website for the version 2 license,
25  * or you may write to the Free Software Foundation, Inc.,
26  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
27  */
28 
29 #include <pgm_base.h>
30 #include <confirm.h>
31 #include <gestfich.h>
32 #include <id.h>
33 #include <project.h>            // For PROJECT_VAR_NAME definition
34 #include <fp_lib_table.h>       // For KICAD6_FOOTPRINT_DIR definition
35 
36 #include <cvpcb_mainframe.h>
37 #include <dialog_config_equfiles.h>
38 #include <project/project_file.h>
39 #include <settings/settings_manager.h>
40 #include <wildcards_and_files_ext.h>
41 
42 #include <wx/filedlg.h>
43 
44 
DIALOG_CONFIG_EQUFILES(CVPCB_MAINFRAME * aParent)45 DIALOG_CONFIG_EQUFILES::DIALOG_CONFIG_EQUFILES( CVPCB_MAINFRAME* aParent ) :
46     DIALOG_CONFIG_EQUFILES_BASE( aParent )
47 {
48     m_Parent = aParent;
49 
50     PROJECT& prj = Prj();
51     SetTitle( wxString::Format( _( "Project file: '%s'" ), prj.GetProjectFullName() ) );
52 
53     Init( );
54 
55     GetSizer()->SetSizeHints( this );
56     Center();
57 }
58 
59 
Init()60 void DIALOG_CONFIG_EQUFILES::Init()
61 {
62     m_sdbSizerOK->SetDefault();
63     m_ListChanged = false;
64 
65     PROJECT_FILE& project = Prj().GetProjectFile();
66 
67     if( !project.m_EquivalenceFiles.empty() )
68     {
69         wxArrayString arr;
70 
71         for( const auto& entry : project.m_EquivalenceFiles )
72             arr.Add( entry );
73 
74         m_ListEquiv->InsertItems( arr, 0 );
75     }
76 
77     if( getEnvVarCount() < 2 )
78         m_gridEnvVars->AppendRows(2 - getEnvVarCount() );
79 
80     wxString evValue;
81     int row = 0;
82 
83     m_gridEnvVars->SetCellValue( row++, 0, PROJECT_VAR_NAME );
84     m_gridEnvVars->SetCellValue( row, 0, FP_LIB_TABLE::GlobalPathEnvVariableName() );
85 
86     for( row = 0; row < getEnvVarCount(); row++ )
87     {
88         if( wxGetEnv( m_gridEnvVars->GetCellValue( row, 0 ), &evValue ) )
89             m_gridEnvVars->SetCellValue( row, 1, evValue );
90     }
91 
92     m_gridEnvVars->AutoSizeColumns();
93 
94 }
95 
96 
OnEditEquFile(wxCommandEvent & event)97 void DIALOG_CONFIG_EQUFILES::OnEditEquFile( wxCommandEvent& event )
98 {
99     wxString    editorname = Pgm().GetTextEditor();
100 
101     if( editorname.IsEmpty() )
102     {
103         wxMessageBox( _( "No text editor selected in KiCad.  Please choose one." ) );
104         return;
105     }
106 
107     wxArrayInt selections;
108     m_ListEquiv->GetSelections( selections );
109 
110     for( unsigned ii = 0; ii < selections.GetCount(); ii++ )
111     {
112         ExecuteFile( editorname, wxExpandEnvVars( m_ListEquiv->GetString( selections[ii] ) ) );
113         m_ListChanged = true;
114     }
115 }
116 
117 
OnOkClick(wxCommandEvent & event)118 void DIALOG_CONFIG_EQUFILES::OnOkClick( wxCommandEvent& event )
119 {
120     // Save new equ file list if the files list was modified
121     if( m_ListChanged  )
122     {
123         PROJECT_FILE& project = Prj().GetProjectFile();
124 
125         // Recreate equ list
126         project.m_EquivalenceFiles.clear();
127 
128         for( unsigned ii = 0; ii < m_ListEquiv->GetCount(); ii++ )
129             project.m_EquivalenceFiles.emplace_back( m_ListEquiv->GetString( ii ) );
130 
131         Pgm().GetSettingsManager().SaveProject();
132     }
133 
134     EndModal( wxID_OK );
135 }
136 
137 
OnCloseWindow(wxCloseEvent & event)138 void DIALOG_CONFIG_EQUFILES::OnCloseWindow( wxCloseEvent& event )
139 {
140     EndModal( wxID_CANCEL );
141 }
142 
143 
OnButtonMoveUp(wxCommandEvent & event)144 void DIALOG_CONFIG_EQUFILES::OnButtonMoveUp( wxCommandEvent& event )
145 {
146     wxArrayInt selections;
147 
148     m_ListEquiv->GetSelections( selections );
149 
150     if ( selections.GetCount() <= 0 )   // No selection.
151         return;
152 
153     if( selections[0] == 0 )            // The first lib is selected. cannot move up it
154         return;
155 
156     wxArrayString libnames = m_ListEquiv->GetStrings();
157 
158     for( size_t ii = 0; ii < selections.GetCount(); ii++ )
159     {
160         int jj = selections[ii];
161         std::swap( libnames[jj],  libnames[jj-1] );
162     }
163 
164     m_ListEquiv->Set( libnames );
165 
166     // Reselect previously selected names
167     for( size_t ii = 0; ii < selections.GetCount(); ii++ )
168     {
169         int jj = selections[ii];
170         m_ListEquiv->SetSelection( jj-1 );
171     }
172 
173     m_ListChanged = true;
174 }
175 
176 
OnButtonMoveDown(wxCommandEvent & event)177 void DIALOG_CONFIG_EQUFILES::OnButtonMoveDown( wxCommandEvent& event )
178 {
179     wxArrayInt selections;
180     m_ListEquiv->GetSelections( selections );
181 
182     if ( selections.GetCount() <= 0 )   // No selection.
183         return;
184 
185     // The last lib is selected. cannot move down it
186     if( selections.Last() == int( m_ListEquiv->GetCount()-1 ) )
187         return;
188 
189     wxArrayString libnames = m_ListEquiv->GetStrings();
190 
191     for( int ii = selections.GetCount()-1; ii >= 0; ii-- )
192     {
193         int jj = selections[ii];
194         std::swap( libnames[jj],  libnames[jj+1] );
195     }
196 
197     m_ListEquiv->Set( libnames );
198 
199     // Reselect previously selected names
200     for( size_t ii = 0; ii < selections.GetCount(); ii++ )
201     {
202         int jj = selections[ii];
203         m_ListEquiv->SetSelection( jj+1 );
204     }
205 
206     m_ListChanged = true;
207 }
208 
209 
210 /* Remove a library to the library list.
211  * The real list (g_LibName_List) is not changed, so the change can be canceled
212  */
OnRemoveFiles(wxCommandEvent & event)213 void DIALOG_CONFIG_EQUFILES::OnRemoveFiles( wxCommandEvent& event )
214 {
215     wxArrayInt selections;
216     m_ListEquiv->GetSelections( selections );
217 
218     std::sort( selections.begin(), selections.end() );
219 
220     for( int ii = selections.GetCount()-1; ii >= 0; ii-- )
221     {
222         m_ListEquiv->Delete( selections[ii] );
223         m_ListChanged = true;
224     }
225 }
226 
227 
OnAddFiles(wxCommandEvent & event)228 void DIALOG_CONFIG_EQUFILES::OnAddFiles( wxCommandEvent& event )
229 {
230     wxString   equFilename;
231     wxFileName fn;
232 
233     wxListBox* list = m_ListEquiv;
234 
235     // Get a default path to open the file dialog:
236     wxString libpath;
237     wxArrayInt selectedRows	= m_gridEnvVars->GetSelectedRows();
238 
239     int row = selectedRows.GetCount() ? selectedRows[0] :
240                 m_gridEnvVars->GetGridCursorRow();
241 
242     libpath = m_gridEnvVars->GetCellValue( wxGridCellCoords( row, 1 ) );
243 
244     wxFileDialog FilesDialog( this, _( "Footprint Association File" ), libpath,
245                               wxEmptyString, EquFileWildcard(),
246                               wxFD_DEFAULT_STYLE | wxFD_MULTIPLE );
247 
248     if( FilesDialog.ShowModal() != wxID_OK )
249         return;
250 
251     wxArrayString Filenames;
252     FilesDialog.GetPaths( Filenames );
253 
254     for( unsigned jj = 0; jj < Filenames.GetCount(); jj++ )
255     {
256         fn = Filenames[jj];
257         equFilename.Empty();
258 
259         if( isPathRelativeAllowed() ) // try to use relative path
260         {
261             for( row = 0; row < getEnvVarCount(); row++ )
262             {
263                 libpath = m_gridEnvVars->GetCellValue( wxGridCellCoords( row, 1 ) );
264 
265                 if( fn.MakeRelativeTo( libpath ) )
266                 {
267                     equFilename.Printf( wxT( "${%s}%c%s" ),
268                             m_gridEnvVars->GetCellValue( wxGridCellCoords( row, 0 ) ),
269                             fn.GetPathSeparator(), fn.GetFullPath() );
270                     break;
271                 }
272             }
273         }
274 
275         if( equFilename.IsEmpty() )
276             equFilename = Filenames[jj];
277 
278         // Add or insert new library name, if not already in list
279         if( list->FindString( equFilename, fn.IsCaseSensitive() ) == wxNOT_FOUND )
280         {
281             m_ListChanged = true;
282             equFilename.Replace( wxT( "\\" ), wxT( "/" ) );     // Use unix separators only.
283             list->Append( equFilename );
284         }
285         else
286         {
287             wxString msg;
288             msg.Printf( _( "File '%s' already exists in list." ), equFilename.GetData() );
289             DisplayError( this, msg );
290         }
291     }
292 }
293