KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pagelayout_editor/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) 2013 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * @author Jean-Pierre Charras, jp.charras at wanadoo.fr
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
23#include <confirm.h>
24#include <gestfich.h>
27#include <paths.h>
28#include <widgets/wx_infobar.h>
30
31#include <kiplatform/io.h>
32
33#include "pl_editor_frame.h"
34#include "pl_editor_id.h"
35
36#include <wx/filedlg.h>
37#include <wx/filename.h>
38#include <wx/stdpaths.h>
39#include <kiplatform/ui.h>
40
42{
43 wxCommandEvent saveEvent;
44 saveEvent.SetId( wxID_SAVE );
45 Files_io( saveEvent );
46
47 return !IsContentModified();
48}
49
50
51void PL_EDITOR_FRAME::OnFileHistory( wxCommandEvent& event )
52{
53 wxString filename;
54
55 filename = GetFileFromHistory( event.GetId(), _( "Drawing Sheet File" ) );
56
57 if( !filename.IsEmpty() )
58 {
59 if( IsContentModified() )
60 {
61 if( !HandleUnsavedChanges( this, _( "The current drawing sheet has been modified. "
62 "Save changes?" ),
63 [&]() -> bool
64 {
65 return saveCurrentPageLayout();
66 } ) )
67 {
68 return;
69 }
70 }
71
72 ::wxSetWorkingDirectory( ::wxPathOnly( filename ) );
73
74 if( LoadDrawingSheetFile( filename ) )
75 {
76 wxString msg;
77 msg.Printf( _( "File '%s' loaded"), filename );
78 SetStatusText( msg );
79 }
80
82 }
83}
84
85
86void PL_EDITOR_FRAME::OnClearFileHistory( wxCommandEvent& aEvent )
87{
89}
90
91
92/* File commands. */
93void PL_EDITOR_FRAME::Files_io( wxCommandEvent& event )
94{
95 wxString msg;
96 int id = event.GetId();
97 wxString filename = GetCurrentFileName();
99
100 if( filename.IsEmpty() && id == wxID_SAVE )
101 id = wxID_SAVEAS;
102
103 if( ( id == wxID_NEW || id == wxID_OPEN ) && IsContentModified() )
104 {
105 if( !HandleUnsavedChanges( this, _( "The current drawing sheet has been modified. "
106 "Save changes?" ),
107 [&]() -> bool
108 {
109 return saveCurrentPageLayout();
110 } ) )
111 {
112 return;
113 }
114 }
115
116 switch( id )
117 {
118 case wxID_NEW:
119 pglayout.AllowVoidList( true );
120 SetCurrentFileName( wxEmptyString );
121 pglayout.ClearList();
123 break;
124
126 {
127 wxFileDialog openFileDialog( this, _( "Append Existing Drawing Sheet" ),
128 wxEmptyString, wxEmptyString,
130
132
133 if( openFileDialog.ShowModal() == wxID_CANCEL )
134 return;
135
136 filename = openFileDialog.GetPath();
137
138 if( !InsertDrawingSheetFile( filename ) )
139 {
140 msg.Printf( _( "Unable to load %s file" ), filename );
141 DisplayErrorMessage( this, msg );
142 }
143 else
144 {
146 HardRedraw();
147 msg.Printf( _( "File '%s' inserted" ), filename );
148 SetStatusText( msg );
149 }
150
151 break;
152 }
153
154 case wxID_OPEN:
155 {
156 wxFileDialog openFileDialog( this, _( "Open Drawing Sheet" ), wxEmptyString, wxEmptyString,
158
160
161 if( openFileDialog.ShowModal() == wxID_CANCEL )
162 return;
163
164 filename = openFileDialog.GetPath();
165
166 if( !LoadDrawingSheetFile( filename ) )
167 {
168 msg.Printf( _( "Unable to load %s file" ), filename );
169 DisplayErrorMessage( this, msg );
170 }
171 else
172 {
174 msg.Printf( _( "File '%s' saved." ), filename );
175 SetStatusText( msg );
176 }
177
178 break;
179 }
180
181 case wxID_SAVE:
182 if( !SaveDrawingSheetFile( filename ) )
183 {
184 msg.Printf( _( "Unable to write '%s'." ), filename );
185 DisplayErrorMessage( this, msg );
186 }
187 else
188 {
189 msg.Printf( _("File '%s' saved."), filename );
190 SetStatusText( msg );
191 }
192
193 break;
194
195 case wxID_SAVEAS:
196 {
197 wxString dir = PATHS::GetUserTemplatesPath();
198 wxFileDialog openFileDialog( this, _( "Save Drawing Sheet As" ), dir, wxEmptyString,
200 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
201
203
204 if( openFileDialog.ShowModal() == wxID_CANCEL )
205 return;
206
207 filename = openFileDialog.GetPath();
208 // Ensure the file has the right extension:
209 // because a name like name.subname.subsubname is legal,
210 // add the right extension without replacing the wxFileName
211 // extension
212 wxFileName fn(filename);
213
214 if( fn.GetExt() != FILEEXT::DrawingSheetFileExtension )
215 filename << wxT( "." ) << FILEEXT::DrawingSheetFileExtension;
216
217 if( !SaveDrawingSheetFile( filename ) )
218 {
219 msg.Printf( _( "Failed to create file '%s'." ), filename );
220 DisplayErrorMessage( this, msg );
221 }
222 else
223 {
224 msg.Printf( _( "File '%s' saved." ), filename );
225 SetStatusText( msg );
226
227 SetCurrentFileName( filename );
229 }
230
231 break;
232 }
233
234 default:
235 break;
236 }
237}
238
239
240bool PL_EDITOR_FRAME::LoadDrawingSheetFile( const wxString& aFullFileName )
241{
242 if( wxFileExists( aFullFileName ) )
243 {
244 wxString msg;
245
246 if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( aFullFileName, &msg ) )
247 {
249 wxString::Format( _( "Error loading drawing sheet '%s'." ),
250 aFullFileName ),
251 msg );
252 return false;
253 }
254
255 SetCurrentFileName( aFullFileName );
256 UpdateFileHistory( aFullFileName );
257 GetScreen()->SetContentModified( false );
258
259 wxFileName fn = aFullFileName;
260 m_infoBar->Dismiss();
261
262 if( DS_DATA_MODEL::GetTheInstance().GetFileFormatVersionAtLoad() < SEXPR_WORKSHEET_FILE_VERSION )
263 {
264 m_infoBar->RemoveAllButtons();
265 m_infoBar->AddCloseButton();
266 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
267 "It will be converted to the new format when saved." ),
268 wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE );
269 }
270
271 if( fn.FileExists() && !fn.IsFileWritable() )
272 {
273 m_infoBar->RemoveAllButtons();
274 m_infoBar->AddCloseButton();
275 m_infoBar->ShowMessage( _( "Layout file is read only." ),
276 wxICON_WARNING, WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE );
277 }
278
279 return true;
280 }
281
282 return false;
283}
284
285
286bool PL_EDITOR_FRAME::InsertDrawingSheetFile( const wxString& aFullFileName )
287{
288 if( wxFileExists( aFullFileName ) )
289 {
290 const bool append = true;
292 DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( aFullFileName, nullptr, append );
293 return true;
294 }
295
296 return false;
297}
298
299
300bool PL_EDITOR_FRAME::SaveDrawingSheetFile( const wxString& aFullFileName )
301{
302 if( !aFullFileName.IsEmpty() )
303 {
304 wxString tempFile = wxFileName::CreateTempFileName( "pledit" );
305
306 try
307 {
309 }
310 catch( const IO_ERROR& )
311 {
312 // In case we started a file but didn't fully write it, clean up
313 wxRemoveFile( tempFile);
314
315 return false;
316 }
317
318 // Preserve the permissions of the current file
319 KIPLATFORM::IO::DuplicatePermissions( aFullFileName, tempFile );
320
321 if( !wxRenameFile( tempFile, aFullFileName ) )
322 return false;
323
324 if( m_infoBar->GetMessageType() == WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE )
325 m_infoBar->Dismiss();
326
327 GetScreen()->SetContentModified( false );
329 return true;
330 }
331
332 return false;
333}
334
336{
337 for( const wxFileName& file : m_AcceptedFiles )
338 OpenProjectFiles( { file.GetFullPath() }, KICTL_CREATE );
339}
void SetContentModified(bool aModified=true)
Definition base_screen.h:55
Handle the graphic items list to draw/plot the frame and title block.
bool LoadDrawingSheet(const wxString &aFullFileName, wxString *aMsg, bool aAppend=false)
Populate the list with a custom layout or the default layout if no custom layout is available.
static DS_DATA_MODEL & GetTheInstance()
Return the instance of DS_DATA_MODEL used in the application.
void AllowVoidList(bool Allow)
In KiCad applications, a drawing sheet is needed So if the list is empty, a default drawing sheet is ...
void ClearList()
Erase the list of items.
void Save(const wxString &aFullFileName)
Save the description in a file.
std::vector< wxFileName > m_AcceptedFiles
WX_INFOBAR * m_infoBar
void UpdateFileHistory(const wxString &FullFileName, FILE_HISTORY *aFileHistory=nullptr)
Update the list of recently opened files.
virtual void ClearFileHistory()
Remove all files from the file history.
wxString GetFileFromHistory(int cmdId, const wxString &type, FILE_HISTORY *aFileHistory=nullptr)
Fetch the file name from the file history list.
virtual BASE_SCREEN * GetScreen() const
Return a pointer to a BASE_SCREEN or one of its derivatives.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
static wxString GetUserTemplatesPath()
Gets the user path for custom templates.
Definition paths.cpp:71
bool OpenProjectFiles(const std::vector< wxString > &aFileSet, int aCtl) override
Open a project or set of files given by aFileList.
void OnNewDrawingSheet()
Must be called to initialize parameters when a new drawing sheet is loaded.
void SetCurrentFileName(const wxString &aName)
Store the current layout description file filename.
bool IsContentModified() const override
Get if the drawing sheet has been modified but not saved.
void Files_io(wxCommandEvent &event)
void OnClearFileHistory(wxCommandEvent &aEvent)
wxString GetCurrentFileName() const override
void OnFileHistory(wxCommandEvent &event)
void DoWithAcceptedFiles() override
Execute action on accepted dropped file.
void UpdateTitleAndInfo()
Display the short filename (if exists) loaded file on the caption of the main window.
bool SaveDrawingSheetFile(const wxString &aFullFileName)
Save the current layout in a .kicad_wks drawing sheet file.
bool InsertDrawingSheetFile(const wxString &aFullFileName)
Load a .kicad_wks drawing sheet file, and add items to the current layout list.
void SaveCopyInUndoList()
Save a copy of the description (in a S expr string) for Undo/redo commands.
void HardRedraw() override
Refresh the library tree and redraw the window.
bool LoadDrawingSheetFile(const wxString &aFullFileName)
Load a .kicad_wks drawing sheet file.
bool HandleUnsavedChanges(wxWindow *aParent, const wxString &aMessage, const std::function< bool()> &aSaveFunction)
Display a dialog with Save, Cancel and Discard Changes buttons.
Definition confirm.cpp:146
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 SEXPR_WORKSHEET_FILE_VERSION
This file contains the file format version information for the s-expression drawing sheet file format...
#define _(s)
static const std::string DrawingSheetFileExtension
static wxString DrawingSheetFileWildcard()
#define KICTL_CREATE
caller thinks requested project files may not exist.
bool DuplicatePermissions(const wxString &aSrc, const wxString &aDest)
Duplicates the file security data from one file to another ensuring that they are the same between bo...
Definition unix/io.cpp:55
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:640
@ ID_APPEND_DESCR_FILE
Definition of file extensions used in Kicad.