KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_embedded_files.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 KiCad Developers, see AUTHORS.TXT for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 3
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/gpl-3.0.html
19 * or you may search the http://www.gnu.org website for the version 3 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <bitmaps.h>
26#include <embedded_files.h>
27#include <kidialog.h>
29#include <widgets/wx_grid.h>
30
31#include <wx/clipbrd.h>
32#include <wx/dirdlg.h>
33#include <wx/ffile.h>
34#include <wx/filedlg.h>
35#include <wx/filename.h>
36#include <wx/menu.h>
37
40 m_files( aFiles )
41{
43
44 for( auto& [name, file] : m_files->EmbeddedFileMap() )
45 {
47 m_localFiles->AddFile( newFile );
48 }
49
50 // Set up the standard buttons
51 m_delete_button->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
52 m_browse_button->SetBitmap( KiBitmapBundle( BITMAPS::small_folder ) );
53 m_files_grid->SetMargins( 0 - wxSYS_VSCROLL_X, 0 );
55}
56
57
58void PANEL_EMBEDDED_FILES::onSize( wxSizeEvent& event )
59{
60 resizeGrid();
61}
62
63
65{
66 int panel_width = GetClientRect().GetWidth();
67 int first_width = m_files_grid->GetColSize( 0 );
68 int second_width = m_files_grid->GetColSize( 1 );
69
70 double ratio;
71
72 if( first_width + second_width > 0 )
73 ratio = (double)first_width / (double)( first_width + second_width );
74 else
75 ratio = 0.3;
76
77
78 m_files_grid->SetColSize( 0, panel_width * ratio );
79 m_files_grid->SetColSize( 1, panel_width * ( 1 - ratio ) );
80 Layout();
81}
82
83
85{
86 wxMenu menu;
87 menu.Append( wxID_COPY, _( "Copy Embedded Reference" ) );
88
89 menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
90 [&]( wxCommandEvent& )
91 {
92 int row = event.GetRow();
93 if( row >= 0 && row < m_files_grid->GetNumberRows() )
94 {
95 wxString cellValue = m_files_grid->GetCellValue( row, 1 );
96
97 if( wxTheClipboard->Open() )
98 {
99 wxTheClipboard->SetData( new wxTextDataObject( cellValue ) );
100 wxTheClipboard->Close();
101 }
102 }
103 }, wxID_COPY );
104
105 PopupMenu( &menu );
106}
107
108
110{
111 m_files_grid->ClearGrid();
112
113 if( m_files_grid->GetNumberRows() > 0 )
114 m_files_grid->DeleteRows( 0, m_files_grid->GetNumberRows() );
115
116 int ii = 0;
117 for( auto& [name, file] : m_localFiles->EmbeddedFileMap() )
118 {
119 while( m_files_grid->GetNumberRows() < ii + 1 )
120 m_files_grid->AppendRows( 1 );
121
122 m_files_grid->SetCellValue( ii, 0, name );
123 m_files_grid->SetCellValue( ii, 1, file->GetLink() );
124
125 ii++;
126 }
127
129
130 resizeGrid();
131
132 return true;
133}
134
135
137{
139
140 std::vector<EMBEDDED_FILES::EMBEDDED_FILE*> files;
141
142 for( auto it = m_localFiles->EmbeddedFileMap().begin(); it != m_localFiles->EmbeddedFileMap().end(); it++ )
143 files.push_back( it->second );
144
145 for( auto& file : files )
146 {
147 m_files->AddFile( file );
148 m_localFiles->RemoveFile( file->name, false );
149 }
150
152
153 return true;
154}
155
156
157void PANEL_EMBEDDED_FILES::onAddEmbeddedFile( wxCommandEvent& event )
158{
159 wxFileDialog fileDialog( this, _( "Select a file to embed" ), wxEmptyString, wxEmptyString,
160 _( "All files|*.*" ), wxFD_OPEN | wxFD_FILE_MUST_EXIST );
161
162 if( fileDialog.ShowModal() == wxID_OK )
163 {
164 wxFileName fileName( fileDialog.GetPath() );
165 wxString name = fileName.GetFullName();
166
167 if( m_localFiles->HasFile( name ) )
168 {
169 wxString msg = wxString::Format( _( "File '%s' already exists." ),
170 name );
171
172 KIDIALOG errorDlg( m_parent, msg, _( "Confirmation" ),
173 wxOK | wxCANCEL | wxICON_WARNING );
174 errorDlg.SetOKLabel( _( "Overwrite" ) );
175
176 if( errorDlg.ShowModal() != wxID_OK )
177 return;
178
179 for( int ii = 0; ii < m_files_grid->GetNumberRows(); ii++ )
180 {
181 if( m_files_grid->GetCellValue( ii, 0 ) == name )
182 {
183 m_files_grid->DeleteRows( ii );
184 break;
185 }
186 }
187 }
188
189 EMBEDDED_FILES::EMBEDDED_FILE* result = m_localFiles->AddFile( fileName, true );
190
191 if( !result )
192 {
193 wxString msg = wxString::Format( _( "Failed to add file '%s'." ),
194 name );
195
196 KIDIALOG errorDlg( m_parent, msg, _( "Error" ), wxOK | wxICON_ERROR );
197 errorDlg.ShowModal();
198 return;
199 }
200
201 m_files_grid->AppendRows( 1 );
202 int ii = m_files_grid->GetNumberRows() - 1;
203 m_files_grid->SetCellValue( ii, 0, name );
204 m_files_grid->SetCellValue( ii, 1, result->GetLink() );
205 }
206}
207
209{
210 int row = m_files_grid->GetGridCursorRow();
211
212 if( row < 0 )
213 return;
214
215 wxString name = m_files_grid->GetCellValue( row, 0 );
216
218
219 m_files_grid->DeleteRows( row );
220
221 if( row < m_files_grid->GetNumberRows() )
222 m_files_grid->SetGridCursor( row, 0 );
223 else if( m_files_grid->GetNumberRows() > 0 )
224 m_files_grid->SetGridCursor( m_files_grid->GetNumberRows() - 1, 0 );
225}
226
227
228void PANEL_EMBEDDED_FILES::onExportFiles( wxCommandEvent& event )
229{
230 wxDirDialog dirDialog( this, _( "Select a directory to export files" ) );
231
232 if( dirDialog.ShowModal() != wxID_OK )
233 return;
234
235 wxString path = dirDialog.GetPath();
236
237 for( auto& [name, file] : m_localFiles->EmbeddedFileMap() )
238 {
239 wxFileName fileName( path, name );
240
241 if( fileName.FileExists() )
242 {
243 wxString msg = wxString::Format( _( "File '%s' already exists." ),
244 fileName.GetFullName() );
245
246 KIDIALOG errorDlg( m_parent, msg, _( "Confirmation" ),
247 wxOK | wxCANCEL | wxICON_WARNING );
248 errorDlg.SetOKCancelLabels( _( "Overwrite" ), _( "Skip" ) );
249 errorDlg.DoNotShowCheckbox( __FILE__, __LINE__ );
250
251 if( errorDlg.ShowModal() != wxID_OK )
252 continue;
253 }
254
255 bool skip_file = false;
256
257 while( 1 )
258 {
259 if( !fileName.IsDirWritable() )
260 {
261#ifndef __WXMAC__
262 wxString msg = wxString::Format( _( "Directory '%s' is not writable." ),
263 fileName.GetFullName() );
264#else
265 wxString msg = wxString::Format( _( "Folder '%s' is not writable." ),
266 fileName.GetPath() );
267#endif
268 // Don't set a 'do not show again' checkbox for this dialog
269 KIDIALOG errorDlg( m_parent, msg, _( "Error" ), wxYES_NO | wxCANCEL | wxICON_ERROR );
270 errorDlg.SetYesNoCancelLabels( _( "Retry" ), _( "Skip" ), _( "Cancel" ) );
271
272 int result = errorDlg.ShowModal();
273
274 if( result == wxID_CANCEL )
275 {
276 return;
277 }
278 else if( result == wxID_NO )
279 {
280 skip_file = true;
281 break;
282 }
283 }
284 else
285 {
286 break;
287 }
288 }
289
290 if( skip_file )
291 continue;
292
293 wxFFile ffile( fileName.GetFullPath(), wxT( "w" ) );
294
295 if( !ffile.IsOpened() )
296 {
297 wxString msg = wxString::Format( _( "Failed to open file '%s'." ),
298 fileName.GetFullName() );
299
300 KIDIALOG errorDlg( m_parent, msg, _( "Error" ), wxOK | wxICON_ERROR );
301 errorDlg.ShowModal();
302 continue;
303 }
304
305 if( !ffile.Write( file->decompressedData.data(), file->decompressedData.size() ) )
306 {
307 wxString msg = wxString::Format( _( "Failed to write file '%s'." ),
308 fileName.GetFullName() );
309
310 KIDIALOG errorDlg( m_parent, msg, _( "Error" ), wxOK | wxICON_ERROR );
311 errorDlg.ShowModal();
312 }
313 }
314}
const char * name
Definition: DXF_plotter.cpp:57
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap)
Definition: bitmap.cpp:110
void RemoveFile(const wxString &name, bool aErase=true)
Removes a file from the collection and frees the memory.
bool HasFile(const wxString &name) const
void ClearEmbeddedFiles(bool aDeleteFiles=true)
EMBEDDED_FILE * AddFile(const wxFileName &aName, bool aOverwrite)
Loads a file from disk and adds it to the collection.
const std::map< wxString, EMBEDDED_FILE * > & EmbeddedFileMap() const
void SetAreFontsEmbedded(bool aEmbedFonts)
bool GetAreFontsEmbedded() const
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: kidialog.h:43
void DoNotShowCheckbox(wxString file, int line)
Checks the 'do not show again' setting for the dialog.
Definition: kidialog.cpp:51
bool SetOKCancelLabels(const ButtonLabel &ok, const ButtonLabel &cancel) override
Shows the 'do not show again' checkbox.
Definition: kidialog.h:53
int ShowModal() override
Definition: kidialog.cpp:95
Class PANEL_EMBEDDED_FILES_BASE.
EMBEDDED_FILES * m_files
PANEL_EMBEDDED_FILES(wxWindow *parent, EMBEDDED_FILES *aFiles)
void onGridRightClick(wxGridEvent &event) override
void onDeleteEmbeddedFile(wxCommandEvent &event) override
bool TransferDataToWindow() override
void onSize(wxSizeEvent &event) override
EMBEDDED_FILES * m_localFiles
void onExportFiles(wxCommandEvent &event) override
void onAddEmbeddedFile(wxCommandEvent &event) override
bool TransferDataFromWindow() override
void SetBitmap(const wxBitmapBundle &aBmp)
void EnableAlternateRowColors(bool aEnable=true)
Enable alternate row highlighting, where every odd row has a different background color than the even...
Definition: wx_grid.cpp:305
#define _(s)
This file is part of the common library.