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, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <confirm.h>
28#include <gestfich.h>
31#include <paths.h>
32#include <widgets/wx_infobar.h>
34
35#include <kiplatform/io.h>
36
37#include "pl_editor_frame.h"
38#include "pl_editor_id.h"
39#include "properties_frame.h"
40
41#include <wx/filedlg.h>
42#include <wx/filename.h>
43#include <wx/stdpaths.h>
44#include <kiplatform/ui.h>
45
47{
48 wxCommandEvent saveEvent;
49 saveEvent.SetId( wxID_SAVE );
50 Files_io( saveEvent );
51
52 return !IsContentModified();
53}
54
55
56void PL_EDITOR_FRAME::OnFileHistory( wxCommandEvent& event )
57{
58 wxString filename;
59
60 filename = GetFileFromHistory( event.GetId(), _( "Drawing Sheet File" ) );
61
62 if( !filename.IsEmpty() )
63 {
64 if( IsContentModified() )
65 {
66 if( !HandleUnsavedChanges( this, _( "The current drawing sheet has been modified. "
67 "Save changes?" ),
68 [&]() -> bool
69 {
70 return saveCurrentPageLayout();
71 } ) )
72 {
73 return;
74 }
75 }
76
77 ::wxSetWorkingDirectory( ::wxPathOnly( filename ) );
78
79 if( LoadDrawingSheetFile( filename ) )
80 {
81 wxString msg;
82 msg.Printf( _( "File '%s' loaded"), filename );
83 SetStatusText( msg );
84 }
85
87 }
88}
89
90
91void PL_EDITOR_FRAME::OnClearFileHistory( wxCommandEvent& aEvent )
92{
94}
95
96
97/* File commands. */
98void PL_EDITOR_FRAME::Files_io( wxCommandEvent& event )
99{
100 wxString msg;
101 int id = event.GetId();
102 wxString filename = GetCurrentFileName();
104
105 if( filename.IsEmpty() && id == wxID_SAVE )
106 id = wxID_SAVEAS;
107
108 if( ( id == wxID_NEW || id == wxID_OPEN ) && IsContentModified() )
109 {
110 if( !HandleUnsavedChanges( this, _( "The current drawing sheet has been modified. "
111 "Save changes?" ),
112 [&]() -> bool
113 {
114 return saveCurrentPageLayout();
115 } ) )
116 {
117 return;
118 }
119 }
120
121 switch( id )
122 {
123 case wxID_NEW:
124 pglayout.AllowVoidList( true );
125 SetCurrentFileName( wxEmptyString );
126 pglayout.ClearList();
128 break;
129
131 {
132 wxFileDialog openFileDialog( this, _( "Append Existing Drawing Sheet" ),
133 wxEmptyString, wxEmptyString,
135
137
138 if( openFileDialog.ShowModal() == wxID_CANCEL )
139 return;
140
141 filename = openFileDialog.GetPath();
142
143 if( !InsertDrawingSheetFile( filename ) )
144 {
145 msg.Printf( _( "Unable to load %s file" ), filename );
146 DisplayErrorMessage( this, msg );
147 }
148 else
149 {
151 HardRedraw();
152 msg.Printf( _( "File '%s' inserted" ), filename );
153 SetStatusText( msg );
154 }
155
156 break;
157 }
158
159 case wxID_OPEN:
160 {
161 wxFileDialog openFileDialog( this, _( "Open Drawing Sheet" ), wxEmptyString, wxEmptyString,
163
165
166 if( openFileDialog.ShowModal() == wxID_CANCEL )
167 return;
168
169 filename = openFileDialog.GetPath();
170
171 if( !LoadDrawingSheetFile( filename ) )
172 {
173 msg.Printf( _( "Unable to load %s file" ), filename );
174 DisplayErrorMessage( this, msg );
175 }
176 else
177 {
179 msg.Printf( _( "File '%s' saved." ), filename );
180 SetStatusText( msg );
181 }
182
183 break;
184 }
185
186 case wxID_SAVE:
187 if( !SaveDrawingSheetFile( filename ) )
188 {
189 msg.Printf( _( "Unable to write '%s'." ), filename );
190 DisplayErrorMessage( this, msg );
191 }
192 else
193 {
194 msg.Printf( _("File '%s' saved."), filename );
195 SetStatusText( msg );
196 }
197
198 break;
199
200 case wxID_SAVEAS:
201 {
202 wxString dir = PATHS::GetUserTemplatesPath();
203 wxFileDialog openFileDialog( this, _( "Save Drawing Sheet As" ), dir, wxEmptyString,
205 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
206
208
209 if( openFileDialog.ShowModal() == wxID_CANCEL )
210 return;
211
212 filename = openFileDialog.GetPath();
213 // Ensure the file has the right extension:
214 // because a name like name.subname.subsubname is legal,
215 // add the right extension without replacing the wxFileName
216 // extension
217 wxFileName fn(filename);
218
219 if( fn.GetExt() != FILEEXT::DrawingSheetFileExtension )
220 filename << wxT( "." ) << FILEEXT::DrawingSheetFileExtension;
221
222 if( !SaveDrawingSheetFile( filename ) )
223 {
224 msg.Printf( _( "Failed to create file '%s'." ), filename );
225 DisplayErrorMessage( this, msg );
226 }
227 else
228 {
229 msg.Printf( _( "File '%s' saved." ), filename );
230 SetStatusText( msg );
231
232 SetCurrentFileName( filename );
234 }
235
236 break;
237 }
238
239 default:
240 break;
241 }
242}
243
244
245bool PL_EDITOR_FRAME::LoadDrawingSheetFile( const wxString& aFullFileName )
246{
247 if( wxFileExists( aFullFileName ) )
248 {
249 wxString msg;
250
251 if( !DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( aFullFileName, &msg ) )
252 {
254 wxString::Format( _( "Error loading drawing sheet '%s'." ),
255 aFullFileName ),
256 msg );
257 return false;
258 }
259
260 SetCurrentFileName( aFullFileName );
261 UpdateFileHistory( aFullFileName );
262 GetScreen()->SetContentModified( false );
263
264 wxFileName fn = aFullFileName;
265 m_infoBar->Dismiss();
266
267 if( DS_DATA_MODEL::GetTheInstance().GetFileFormatVersionAtLoad() < SEXPR_WORKSHEET_FILE_VERSION )
268 {
269 m_infoBar->RemoveAllButtons();
270 m_infoBar->AddCloseButton();
271 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
272 "It will be converted to the new format when saved." ),
274 }
275
276 if( fn.FileExists() && !fn.IsFileWritable() )
277 {
278 m_infoBar->RemoveAllButtons();
279 m_infoBar->AddCloseButton();
280 m_infoBar->ShowMessage( _( "Layout file is read only." ),
282 }
283
284 return true;
285 }
286
287 return false;
288}
289
290
291bool PL_EDITOR_FRAME::InsertDrawingSheetFile( const wxString& aFullFileName )
292{
293 if( wxFileExists( aFullFileName ) )
294 {
295 const bool append = true;
297 DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( aFullFileName, nullptr, append );
298 return true;
299 }
300
301 return false;
302}
303
304
305bool PL_EDITOR_FRAME::SaveDrawingSheetFile( const wxString& aFullFileName )
306{
307 if( !aFullFileName.IsEmpty() )
308 {
309 wxString tempFile = wxFileName::CreateTempFileName( "pledit" );
310
311 try
312 {
314 }
315 catch( const IO_ERROR& )
316 {
317 // In case we started a file but didn't fully write it, clean up
318 wxRemoveFile( tempFile);
319
320 return false;
321 }
322
323 // Preserve the permissions of the current file
324 KIPLATFORM::IO::DuplicatePermissions( aFullFileName, tempFile );
325
326 if( !wxRenameFile( tempFile, aFullFileName ) )
327 return false;
328
329 if( m_infoBar->GetMessageType() == WX_INFOBAR::MESSAGE_TYPE::OUTDATED_SAVE )
330 m_infoBar->Dismiss();
331
332 GetScreen()->SetContentModified( false );
334 return true;
335 }
336
337 return false;
338}
339
341{
342 for( const wxFileName& file : m_AcceptedFiles )
343 OpenProjectFiles( { file.GetFullPath() }, KICTL_CREATE );
344}
void SetContentModified(bool aModified=true)
Definition base_screen.h:59
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.
@ OUTDATED_SAVE
OUTDATED_SAVE Messages that should be cleared on save.
Definition wx_infobar.h:96
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:131
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
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:51
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:717
@ ID_APPEND_DESCR_FILE
Definition of file extensions used in Kicad.