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 (C) 2017-2023 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
46{
47 wxCommandEvent saveEvent;
48 saveEvent.SetId( wxID_SAVE );
49 Files_io( saveEvent );
50
51 return !IsContentModified();
52}
53
54
55void PL_EDITOR_FRAME::OnFileHistory( wxCommandEvent& event )
56{
57 wxString filename;
58
59 filename = GetFileFromHistory( event.GetId(), _( "Drawing Sheet File" ) );
60
61 if( filename != wxEmptyString )
62 {
63 if( IsContentModified() )
64 {
65 if( !HandleUnsavedChanges( this, _( "The current drawing sheet has been modified. "
66 "Save changes?" ),
67 [&]() -> bool
68 {
69 return saveCurrentPageLayout();
70 } ) )
71 {
72 return;
73 }
74 }
75
76 ::wxSetWorkingDirectory( ::wxPathOnly( filename ) );
77
78 if( LoadDrawingSheetFile( filename ) )
79 {
80 wxString msg;
81 msg.Printf( _( "File \"%s\" loaded"), filename );
82 SetStatusText( msg );
83 }
84
86 }
87}
88
89
90void PL_EDITOR_FRAME::OnClearFileHistory( wxCommandEvent& aEvent )
91{
93}
94
95
96/* File commands. */
97void PL_EDITOR_FRAME::Files_io( wxCommandEvent& event )
98{
99 wxString msg;
100 int id = event.GetId();
101 wxString filename = GetCurrentFileName();
103
104 if( filename.IsEmpty() && id == wxID_SAVE )
105 id = wxID_SAVEAS;
106
107 if( ( id == wxID_NEW || id == wxID_OPEN ) && IsContentModified() )
108 {
109 if( !HandleUnsavedChanges( this, _( "The current drawing sheet has been modified. "
110 "Save changes?" ),
111 [&]() -> bool
112 {
113 return saveCurrentPageLayout();
114 } ) )
115 {
116 return;
117 }
118 }
119
120 switch( id )
121 {
122 case wxID_NEW:
123 pglayout.AllowVoidList( true );
124 SetCurrentFileName( wxEmptyString );
125 pglayout.ClearList();
127 break;
128
130 {
131 wxFileDialog openFileDialog( this, _( "Append Existing Drawing Sheet" ),
132 wxEmptyString, wxEmptyString,
134
135 if( openFileDialog.ShowModal() == wxID_CANCEL )
136 return;
137
138 filename = openFileDialog.GetPath();
139
140 if( !InsertDrawingSheetFile( filename ) )
141 {
142 msg.Printf( _( "Unable to load %s file" ), filename );
143 DisplayErrorMessage( this, msg );
144 }
145 else
146 {
148 HardRedraw();
149 msg.Printf( _( "File \"%s\" inserted" ), filename );
150 SetStatusText( msg );
151 }
152 }
153 break;
154
155 case wxID_OPEN:
156 {
157 wxFileDialog openFileDialog( this, _( "Open Drawing Sheet" ), wxEmptyString, wxEmptyString,
159
160 if( openFileDialog.ShowModal() == wxID_CANCEL )
161 return;
162
163 filename = openFileDialog.GetPath();
164
165 if( !LoadDrawingSheetFile( filename ) )
166 {
167 msg.Printf( _( "Unable to load %s file" ), filename );
168 DisplayErrorMessage( this, msg );
169 }
170 else
171 {
173 msg.Printf( _( "File \"%s\" saved." ), filename );
174 SetStatusText( msg );
175 }
176 }
177 break;
178
179 case wxID_SAVE:
180 if( !SaveDrawingSheetFile( filename ) )
181 {
182 msg.Printf( _( "Unable to write '%s'." ), filename );
183 DisplayErrorMessage( this, msg );
184 }
185 else
186 {
187 msg.Printf( _("File '%s' saved."), filename );
188 SetStatusText( msg );
189 }
190 break;
191
192 case wxID_SAVEAS:
193 {
194 wxString dir = PATHS::GetUserTemplatesPath();
195 wxFileDialog openFileDialog( this, _( "Save Drawing Sheet As" ), dir, wxEmptyString,
197 wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
198
199 if( openFileDialog.ShowModal() == wxID_CANCEL )
200 return;
201
202 filename = openFileDialog.GetPath();
203 // Ensure the file has the right extension:
204 // because a name like name.subname.subsubname is legal,
205 // add the right extension without replacing the wxFileName
206 // extension
207 wxFileName fn(filename);
208
209 if( fn.GetExt() != FILEEXT::DrawingSheetFileExtension )
210 filename << wxT( "." ) << FILEEXT::DrawingSheetFileExtension;
211
212 if( !SaveDrawingSheetFile( filename ) )
213 {
214 msg.Printf( _( "Failed to create file '%s'." ), filename );
215 DisplayErrorMessage( this, msg );
216 }
217 else
218 {
219 msg.Printf( _( "File '%s' saved." ), filename );
220 SetStatusText( msg );
221
222 SetCurrentFileName( filename );
224 }
225 }
226 break;
227
228 default:
229 break;
230 }
231}
232
233
234bool PL_EDITOR_FRAME::LoadDrawingSheetFile( const wxString& aFullFileName )
235{
236 if( wxFileExists( aFullFileName ) )
237 {
238 bool loaded = false;
239
240 loaded = DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( aFullFileName );
241
242 if( !loaded )
243 {
244 ShowInfoBarError( _( "Error reading drawing sheet" ), true );
245 return false;
246 }
247
248 SetCurrentFileName( aFullFileName );
249 UpdateFileHistory( aFullFileName );
250 GetScreen()->SetContentModified( false );
251
252 wxFileName fn = aFullFileName;
254
255 if( DS_DATA_MODEL::GetTheInstance().GetFileFormatVersionAtLoad() < SEXPR_WORKSHEET_FILE_VERSION )
256 {
259 m_infoBar->ShowMessage( _( "This file was created by an older version of KiCad. "
260 "It will be converted to the new format when saved." ),
262 }
263
264 if( fn.FileExists() && !fn.IsFileWritable() )
265 {
268 m_infoBar->ShowMessage( _( "Layout file is read only." ),
270 }
271
272 return true;
273 }
274
275 return false;
276}
277
278
279bool PL_EDITOR_FRAME::InsertDrawingSheetFile( const wxString& aFullFileName )
280{
281 if( wxFileExists( aFullFileName ) )
282 {
283 const bool append = true;
285 DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( aFullFileName, append );
286 return true;
287 }
288
289 return false;
290}
291
292
293bool PL_EDITOR_FRAME::SaveDrawingSheetFile( const wxString& aFullFileName )
294{
295 if( !aFullFileName.IsEmpty() )
296 {
297 wxString tempFile = wxFileName::CreateTempFileName( "pledit" );
298
299 try
300 {
302 }
303 catch( const IO_ERROR& )
304 {
305 // In case we started a file but didn't fully write it, clean up
306 wxRemoveFile( tempFile);
307
308 return false;
309 }
310
311 // Preserve the permissions of the current file
312 KIPLATFORM::IO::DuplicatePermissions( aFullFileName, tempFile );
313
314 if( !wxRenameFile( tempFile, aFullFileName ) )
315 return false;
316
319
320 GetScreen()->SetContentModified( false );
322 return true;
323 }
324
325 return false;
326}
327
329{
330 for( const wxFileName& file : m_AcceptedFiles )
331 OpenProjectFiles( { file.GetFullPath() }, KICTL_CREATE );
332}
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
Handle the graphic items list to draw/plot the frame and title block.
Definition: ds_data_model.h:39
static DS_DATA_MODEL & GetTheInstance()
static function: returns 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 ...
Definition: ds_data_model.h:83
void ClearList()
Erase the list of items.
void Save(const wxString &aFullFileName)
Save the description in a file.
bool LoadDrawingSheet(const wxString &aFullFileName=wxEmptyString, bool Append=false)
Populates the list with a custom layout or the default layout if no custom layout is available.
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.
void ClearFileHistory(FILE_HISTORY *aFileHistory=nullptr)
Removes all files from the file history.
wxString GetFileFromHistory(int cmdId, const wxString &type, FILE_HISTORY *aFileHistory=nullptr)
Fetches the file name from the file history list.
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, WX_INFOBAR::MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
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.
Definition: ki_exception.h:77
static wxString GetUserTemplatesPath()
Gets the user path for custom templates.
Definition: paths.cpp:87
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.
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: wx_infobar.cpp:301
@ OUTDATED_SAVE
OUTDATED_SAVE Messages that should be cleared on save.
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: wx_infobar.cpp:187
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: wx_infobar.cpp:291
MESSAGE_TYPE GetMessageType() const
Definition: wx_infobar.h:100
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: wx_infobar.cpp:154
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:240
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:305
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.
Definition: kiway_player.h:78
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: gtk/io.cpp:40
@ ID_APPEND_DESCR_FILE
Definition: pl_editor_id.h:41
Definition of file extensions used in Kicad.