KiCad PCB EDA Suite
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-2019 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>
30 #include <paths.h>
31 #include <widgets/infobar.h>
33 
34 #include "pl_editor_frame.h"
35 #include "pl_editor_id.h"
36 #include "properties_frame.h"
37 
39 {
40  wxCommandEvent saveEvent;
41  saveEvent.SetId( wxID_SAVE );
42  Files_io( saveEvent );
43 
44  return !IsContentModified();
45 }
46 
47 
48 void PL_EDITOR_FRAME::OnFileHistory( wxCommandEvent& event )
49 {
50  wxString filename;
51 
52  filename = GetFileFromHistory( event.GetId(), _( "Page Layout Description File" ) );
53 
54  if( filename != wxEmptyString )
55  {
56  if( IsContentModified() )
57  {
58  if( !HandleUnsavedChanges( this, _( "The current page layout has been modified. "
59  "Save changes?" ),
60  [&]()->bool { return saveCurrentPageLayout(); } ) )
61  {
62  return;
63  }
64  }
65 
66  ::wxSetWorkingDirectory( ::wxPathOnly( filename ) );
67 
68  if( LoadPageLayoutDescrFile( filename ) )
69  {
70  wxString msg;
71  msg.Printf( _( "File \"%s\" loaded"), filename );
72  SetStatusText( msg );
73  }
74 
76  }
77 }
78 
79 
80 void PL_EDITOR_FRAME::OnClearFileHistory( wxCommandEvent& aEvent )
81 {
83 }
84 
85 
86 /* File commands. */
87 void PL_EDITOR_FRAME::Files_io( wxCommandEvent& event )
88 {
89  wxString msg;
90  int id = event.GetId();
91  wxString filename = GetCurrentFileName();
93 
94  if( filename.IsEmpty() && id == wxID_SAVE )
95  id = wxID_SAVEAS;
96 
97  if( ( id == wxID_NEW || id == wxID_OPEN ) && IsContentModified() )
98  {
99  if( !HandleUnsavedChanges( this, _( "The current page layout has been modified. "
100  "Save changes?" ),
101  [&]()->bool { return saveCurrentPageLayout(); } ) )
102  {
103  return;
104  }
105  }
106 
107  switch( id )
108  {
109  case wxID_NEW:
110  pglayout.AllowVoidList( true );
111  SetCurrentFileName( wxEmptyString );
112  pglayout.ClearList();
113  OnNewPageLayout();
114  break;
115 
117  {
118  wxFileDialog openFileDialog( this, _( "Append Existing Drawing Sheet" ),
119  wxEmptyString, wxEmptyString,
120  PageLayoutDescrFileWildcard(), wxFD_OPEN );
121 
122  if( openFileDialog.ShowModal() == wxID_CANCEL )
123  return;
124 
125  filename = openFileDialog.GetPath();
126 
127  if( ! InsertPageLayoutDescrFile( filename ) )
128  {
129  msg.Printf( _( "Unable to load %s file" ), filename );
130  DisplayErrorMessage( this, msg );
131  }
132  else
133  {
134  GetScreen()->SetModify();
135  HardRedraw();
136  msg.Printf( _( "File \"%s\" inserted" ), filename );
137  SetStatusText( msg );
138  }
139  }
140  break;
141 
142  case wxID_OPEN:
143  {
144  wxFileDialog openFileDialog( this, _( "Open" ), wxEmptyString, wxEmptyString,
145  PageLayoutDescrFileWildcard(), wxFD_OPEN );
146 
147  if( openFileDialog.ShowModal() == wxID_CANCEL )
148  return;
149 
150  filename = openFileDialog.GetPath();
151 
152  if( ! LoadPageLayoutDescrFile( filename ) )
153  {
154  msg.Printf( _( "Unable to load %s file" ), filename );
155  DisplayErrorMessage( this, msg );
156  }
157  else
158  {
159  OnNewPageLayout();
160  msg.Printf( _( "File \"%s\" saved." ), filename );
161  SetStatusText( msg );
162  }
163  }
164  break;
165 
166  case wxID_SAVE:
167  if( !SavePageLayoutDescrFile( filename ) )
168  {
169  msg.Printf( _( "Unable to write \"%s\"" ), filename );
170  DisplayErrorMessage( this, msg );
171  }
172  else
173  {
174  msg.Printf( _("File \"%s\" saved."), filename );
175  SetStatusText( msg );
176  }
177  break;
178 
179  case wxID_SAVEAS:
180  {
181  wxString dir = PATHS::GetUserTemplatesPath();
182  wxFileDialog openFileDialog( this, _( "Save As" ), dir, wxEmptyString,
184  wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
185 
186  if( openFileDialog.ShowModal() == wxID_CANCEL )
187  return;
188 
189  filename = openFileDialog.GetPath();
190  // Ensure the file has the right extension:
191  // because a name like name.subname.subsubname is legal,
192  // add the right extension without replacing the wxFileName
193  // extension
194  wxFileName fn(filename);
195 
196  if( fn.GetExt() != PageLayoutDescrFileExtension )
197  filename << wxT(".") << PageLayoutDescrFileExtension;
198 
199  if( !SavePageLayoutDescrFile( filename ) )
200  {
201  msg.Printf( _( "Unable to create \"%s\"" ), filename );
202  DisplayErrorMessage( this, msg );
203  }
204 
205  else
206  {
207  msg.Printf( _("File \"%s\" saved."), filename );
208  SetStatusText( msg );
209 
210  if( GetCurrentFileName().IsEmpty() )
211  SetCurrentFileName( filename );
212  }
213  }
214  break;
215 
216  default:
217  break;
218  }
219 }
220 
221 
222 bool PL_EDITOR_FRAME::LoadPageLayoutDescrFile( const wxString& aFullFileName )
223 {
224  if( wxFileExists( aFullFileName ) )
225  {
227  SetCurrentFileName( aFullFileName );
228  UpdateFileHistory( aFullFileName );
229  GetScreen()->ClrModify();
230 
231  wxFileName fn = aFullFileName;
232  m_infoBar->Dismiss();
233 
234  if( fn.FileExists() && !fn.IsFileWritable() )
235  {
238  m_infoBar->ShowMessage( _( "Layout file is read only." ), wxICON_WARNING );
239  }
240 
241  return true;
242  }
243 
244  return false;
245 }
246 
247 
248 bool PL_EDITOR_FRAME::InsertPageLayoutDescrFile( const wxString& aFullFileName )
249 {
250  if( wxFileExists( aFullFileName ) )
251  {
252  const bool append = true;
254  DS_DATA_MODEL::GetTheInstance().LoadDrawingSheet( aFullFileName, append );
255  return true;
256  }
257 
258  return false;
259 }
260 
261 
262 bool PL_EDITOR_FRAME::SavePageLayoutDescrFile( const wxString& aFullFileName )
263 {
264  if( !aFullFileName.IsEmpty() )
265  {
266  wxFileName tempFile( aFullFileName );
267  tempFile.SetName( wxT( "." ) + tempFile.GetName() );
268  tempFile.SetExt( tempFile.GetExt() + wxT( "$" ) );
269 
270  try
271  {
272  DS_DATA_MODEL::GetTheInstance().Save( tempFile.GetFullPath() );
273  }
274  catch( const IO_ERROR& )
275  {
276  // In case we started a file but didn't fully write it, clean up
277  wxRemoveFile( tempFile.GetFullPath() );
278 
279  return false;
280  }
281 
282  if( !wxRenameFile( tempFile.GetFullPath(), aFullFileName ) )
283  return false;
284 
285  GetScreen()->ClrModify();
286  return true;
287  }
288 
289  return false;
290 }
void OnFileHistory(wxCommandEvent &event)
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: infobar.cpp:129
void ClearList()
Erase the list of items.
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:207
bool IsContentModified() override
Get if the page layout has been modified but not saved.
wxString PageLayoutDescrFileWildcard()
Handle the graphic items list to draw/plot the frame and title block.
Definition: ds_data_model.h:38
void HardRedraw() override
Refresh the library tree and redraw the window.
void 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.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:265
This file is part of the common library TODO brief description.
This file is part of the common library.
void OnClearFileHistory(wxCommandEvent &aEvent)
void Save(const wxString &aFullFileName)
Save the description in a file.
void UpdateFileHistory(const wxString &FullFileName, FILE_HISTORY *aFileHistory=nullptr)
Update the list of recently opened files.
wxString GetFileFromHistory(int cmdId, const wxString &type, FILE_HISTORY *aFileHistory=nullptr)
Fetches the file name from the file history list.
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: infobar.cpp:171
static DS_DATA_MODEL & GetTheInstance()
static function: returns the instance of DS_DATA_MODEL used in the application
wxString GetCurrentFileName() const override
void AllowVoidList(bool Allow)
In KiCad applications, a page layout description is needed So if the list is empty,...
Definition: ds_data_model.h:81
void OnNewPageLayout()
Must be called to initialize parameters when a new page layout description is loaded.
Definition of file extensions used in Kicad.
static wxString GetUserTemplatesPath()
Gets the user path for custom templates.
Definition: paths.cpp:86
bool SavePageLayoutDescrFile(const wxString &aFullFileName)
Function SavePageLayoutDescrFile Save the current layout in a .kicad_wks page layout descr file.
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: infobar.cpp:282
const std::string PageLayoutDescrFileExtension
void ClearFileHistory(FILE_HISTORY *aFileHistory=nullptr)
Removes all files from the file history.
void SetCurrentFileName(const wxString &aName)
Stores the current layout descr file filename.
WX_INFOBAR * m_infoBar
#define _(s)
Definition: 3d_actions.cpp:33
bool InsertPageLayoutDescrFile(const wxString &aFullFileName)
Function InsertPageLayoutDescrFile Loads a .kicad_wks page layout descr file, and add items to the cu...
bool LoadPageLayoutDescrFile(const wxString &aFullFileName)
Function LoadPageLayoutDescrFile Loads a .kicad_wks page layout descr file.
void ClrModify()
Definition: base_screen.h:60
void SaveCopyInUndoList()
Save a copy of the description (in a S expr string) for Undo/redo commands.
void SetModify()
Definition: base_screen.h:59
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75
virtual BASE_SCREEN * GetScreen() const
Return a pointer to a BASE_SCREEN or one of its derivatives.
void AddCloseButton(const wxString &aTooltip=_("Hide this message."))
Add the default close button to the infobar on the right side.
Definition: infobar.cpp:272
void Files_io(wxCommandEvent &event)