KiCad PCB EDA Suite
kicad_manager_frame.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) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2013 CERN (www.cern.ch)
6  * Copyright (C) 2004-2020 KiCad Developers, see change_log.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include "kicad_id.h"
27 #include "pgm_kicad.h"
28 #include "tree_project_frame.h"
29 #include <bitmaps.h>
30 #include <build_version.h>
31 #include <executable_names.h>
32 #include <filehistory.h>
33 #include <gestfich.h>
34 #include <kiway.h>
35 #include <kiway_express.h>
36 #include <kiway_player.h>
37 #include <launch_ext.h>
38 #include <panel_hotkeys_editor.h>
40 #include <tool/action_toolbar.h>
41 #include <tool/common_control.h>
42 #include <tool/tool_manager.h>
46 
47 #ifdef __WXMAC__
48 #include <MacTypes.h>
49 #include <ApplicationServices/ApplicationServices.h>
50 #endif
51 
52 #include "kicad_manager_frame.h"
53 #include "kicad_settings.h"
54 
55 
56 #define SEP() wxFileName::GetPathSeparator()
57 
58 // Not really useful, provided to save/restore params in project config file,
59 // (Add them in s_KicadManagerParams if any)
60 // Used also to create new .pro files from the kicad.pro template file
61 // for new projects
62 #define GeneralGroupName wxT( "/general" )
63 
64 std::vector<PARAM_CFG*> s_KicadManagerParams;
65 
66 
67 // Menubar and toolbar event table
68 BEGIN_EVENT_TABLE( KICAD_MANAGER_FRAME, EDA_BASE_FRAME )
69  // Window events
70  EVT_SIZE( KICAD_MANAGER_FRAME::OnSize )
72 
73  // Menu events
74  EVT_MENU( wxID_EXIT, KICAD_MANAGER_FRAME::OnExit )
80 
81  // Range menu events
83  KICAD_MANAGER_FRAME::language_change )
84 
86  EVT_MENU( ID_FILE_LIST_CLEAR, KICAD_MANAGER_FRAME::OnClearFileHistory )
87 
88  // Special functions
89  EVT_MENU( ID_INIT_WATCHED_PATHS, KICAD_MANAGER_FRAME::OnChangeWatchedPaths )
90 END_EVENT_TABLE()
91 
92 
93 KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent, const wxString& title,
94  const wxPoint& pos, const wxSize& size ) :
95  EDA_BASE_FRAME( parent, KICAD_MAIN_FRAME_T, title, pos, size,
97  m_leftWin( nullptr ),
98  m_launcher( nullptr ),
99  m_messagesBox( nullptr ),
100  m_mainToolBar( nullptr )
101 {
102  m_active_project = false;
103  m_leftWinWidth = 250; // Default value
104  m_AboutTitle = "KiCad";
105 
106  // Create the status line (bottom of the frame)
107  static const int dims[3] = { -1, -1, 100 };
108 
109  CreateStatusBar( 3 );
110  SetStatusWidths( 3, dims );
111 
112  // Give an icon
113  wxIcon icon;
114  icon.CopyFromBitmap( KiBitmap( icon_kicad_xpm ) );
115  SetIcon( icon );
116 
117  // Give the last size and pos to main window
118  LoadSettings( config() );
119  SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y );
120 
121  // Left window: is the box which display tree project
122  m_leftWin = new TREE_PROJECT_FRAME( this );
123 
124  // Add the wxTextCtrl showing all messages from KiCad:
125  m_messagesBox = new wxTextCtrl( this, wxID_ANY, wxEmptyString,
126  wxDefaultPosition, wxDefaultSize,
127  wxTE_MULTILINE | wxTE_READONLY | wxBORDER_NONE );
128 
129  // Create the manager
130  m_toolManager = new TOOL_MANAGER;
131  m_toolManager->SetEnvironment( nullptr, nullptr, nullptr, this );
132  m_actions = new KICAD_MANAGER_ACTIONS();
133 
134  // Register tools
135  m_toolManager->RegisterTool( new COMMON_CONTROL );
136  m_toolManager->RegisterTool( new KICAD_MANAGER_CONTROL );
137  m_toolManager->InitTools();
138 
139  RecreateBaseHToolbar();
140  RecreateLauncher();
141  ReCreateMenuBar();
142 
143  m_auimgr.SetManagedWindow( this );
144 
145  m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( "MainToolbar" ).Top().Layer(6) );
146 
147  // BestSize() does not always set the actual pane size of m_leftWin to the required value.
148  // It happens when m_leftWin is too large (roughly > 1/3 of the kicad manager frame width.
149  // (Well, BestSize() sets the best size... not the window size)
150  // A trick is to use MinSize() to set the required pane width,
151  // and after give a reasonable MinSize value
152  m_auimgr.AddPane( m_leftWin, EDA_PANE().Palette().Name( "ProjectTree" ).Left().Layer(3)
153  .CaptionVisible( false ).PaneBorder( false )
154  .MinSize( m_leftWinWidth, -1 ).BestSize( m_leftWinWidth, -1 ) );
155 
156  m_auimgr.AddPane( m_launcher, EDA_PANE().HToolbar().Name( "Launcher" ).Top().Layer(1) );
157 
158  m_auimgr.AddPane( m_messagesBox, EDA_PANE().Messages().Name( "MsgPanel" ).Center() );
159 
160  m_auimgr.Update();
161 
162  // Now the actual m_leftWin size is set, give it a reasonable min width
163  m_auimgr.GetPane( m_leftWin ).MinSize( 200, -1 );
164 
165  SetTitle( wxString( "KiCad " ) + GetBuildVersion() );
166 }
167 
168 
170 {
171  // Shutdown all running tools
172  if( m_toolManager )
174 
175  delete m_actions;
176  delete m_toolManager;
177 
178  m_auimgr.UnInit();
179 }
180 
181 
183 {
185  wxASSERT( ret );
186  return ret;
187 }
188 
189 
190 void KICAD_MANAGER_FRAME::SetProjectFileName( const wxString& aFullProjectProFileName )
191 {
192  // ensure file name is absolute:
193  wxFileName fn( aFullProjectProFileName );
194 
195  if( !fn.IsAbsolute() )
196  fn.MakeAbsolute();
197 
198  Prj().SetProjectFullName( fn.GetFullPath() );
199 
200  SetTitle( wxString( "KiCad " ) + GetBuildVersion() );
201  wxString title = GetTitle() + " " + fn.GetFullPath();
202 
203  if( !fn.IsDirWritable() )
204  title += _( " [Read Only]" );
205 
206  SetTitle( title );
207 }
208 
209 
211 {
212  return Prj().GetProjectFullName();
213 }
214 
215 
217 {
218  wxFileName fn( GetProjectFileName() );
219 
220  fn.SetExt( LegacySchematicFileExtension );
221  return fn.GetFullPath();
222 }
223 
224 
226 {
227  wxFileName fn( GetProjectFileName() );
228 
229  fn.SetExt( PcbFileExtension );
230  return fn.GetFullPath();
231 }
232 
233 
235 {
236  wxFileName fn( GetProjectFileName() );
237 
238  fn.SetExt( LegacyPcbFileExtension );
239  return fn.GetFullPath();
240 }
241 
242 
244 {
246 }
247 
248 
250 {
251  return PgmTop().SysSearch();
252 }
253 
254 
256 {
257  return PgmTop().GetHelpFileName();
258 }
259 
260 
261 void KICAD_MANAGER_FRAME::PrintMsg( const wxString& aText )
262 {
263  m_messagesBox->AppendText( aText );
264 }
265 
266 
267 void KICAD_MANAGER_FRAME::OnSize( wxSizeEvent& event )
268 {
269  if( m_auimgr.GetManagedWindow() )
270  m_auimgr.Update();
271 
272  event.Skip();
273 }
274 
275 
276 void KICAD_MANAGER_FRAME::OnCloseWindow( wxCloseEvent& Event )
277 {
278  if( Kiway().PlayersClose( false ) )
279  {
280  int px, py;
281 
282  if( !GetProjectFileName().empty() )
283  UpdateFileHistory( GetProjectFileName(), &PgmTop().GetFileHistory() );
284 
285  if( !IsIconized() ) // save main frame position and size
286  {
287  GetPosition( &px, &py );
288  m_FramePos.x = px;
289  m_FramePos.y = py;
290 
291  GetSize( &px, &py );
292  m_FrameSize.x = px;
293  m_FrameSize.y = py;
294  }
295 
296  Event.SetCanVeto( true );
297 
298  m_leftWin->Show( false );
299 
300  Destroy();
301  }
302 }
303 
304 
305 void KICAD_MANAGER_FRAME::OnExit( wxCommandEvent& event )
306 {
307  Close( true );
308 }
309 
310 
311 void KICAD_MANAGER_FRAME::LoadProject( const wxFileName& aProjectFileName )
312 {
313  // The project file should be valid by the time we get here or something has gone wrong.
314  if( !aProjectFileName.Exists() )
315  return;
316 
317  // Any open KIFACE's must be closed if they are not part of the new project.
318  // (We never want a KIWAY_PLAYER open on a KIWAY that isn't in the same project.)
319  // User is prompted here to close those KIWAY_PLAYERs:
320  if( !Kiway().PlayersClose( false ) )
321  return;
322 
323  // Save the project file for the currently loaded project.
324  if( m_active_project )
326 
327  m_active_project = true;
328  ClearMsg();
329  SetProjectFileName( aProjectFileName.GetFullPath() );
331 
332  if( aProjectFileName.IsDirWritable() )
333  SetMruPath( Prj().GetProjectPath() ); // Only set MRU path if we have write access. Why?
334 
335  UpdateFileHistory( aProjectFileName.GetFullPath(), &PgmTop().GetFileHistory() );
336 
338 
339  SyncToolbars();
340 
341  // Rebuild the list of watched paths.
342  // however this is possible only when the main loop event handler is running,
343  // so we use it to run the rebuild function.
344  wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED, ID_INIT_WATCHED_PATHS );
345 
346  wxPostEvent( this, cmd );
347 
348  PrintPrjInfo();
349 }
350 
351 
352 void KICAD_MANAGER_FRAME::CreateNewProject( const wxFileName& aProjectFileName )
353 {
354  wxCHECK_RET( aProjectFileName.DirExists() && aProjectFileName.IsDirWritable(),
355  "Project folder must exist and be writable to create a new project." );
356 
357  // Init project filename. This clears all elements from the project object.
358  SetProjectFileName( aProjectFileName.GetFullPath() );
359 
360  // Copy kicad.pro file from template folder.
361  if( !aProjectFileName.FileExists() )
362  {
363  wxString srcFileName = sys_search().FindValidPath( "kicad.pro" );
364 
365  // Create a minimal project (.pro) file if the template project file could not be copied.
366  if( !wxFileName::FileExists( srcFileName )
367  || !wxCopyFile( srcFileName, aProjectFileName.GetFullPath() ) )
368  {
370  }
371  }
372 
373  // Ensure a "stub" for a schematic root sheet and a board exist.
374  // It will avoid messages from the schematic editor or the board editor to create a new file
375  // And forces the user to create main files under the right name for the project manager
376  wxFileName fn( aProjectFileName.GetFullPath() );
377  fn.SetExt( LegacySchematicFileExtension );
378 
379  // If a <project>.sch file does not exist, create a "stub" file ( minimal schematic file )
380  if( !fn.FileExists() )
381  {
382  wxFile file( fn.GetFullPath(), wxFile::write );
383 
384  if( file.IsOpened() )
385  file.Write( wxT( "EESchema Schematic File Version 2\n"
386  "EELAYER 25 0\nEELAYER END\n$EndSCHEMATC\n" ) );
387 
388  // wxFile dtor will close the file
389  }
390 
391  // If a <project>.kicad_pcb or <project>.brd file does not exist,
392  // create a .kicad_pcb "stub" file
393  fn.SetExt( KiCadPcbFileExtension );
394  wxFileName leg_fn( fn );
395  leg_fn.SetExt( LegacyPcbFileExtension );
396 
397  if( !fn.FileExists() && !leg_fn.FileExists() )
398  {
399  wxFile file( fn.GetFullPath(), wxFile::write );
400 
401  if( file.IsOpened() )
402  file.Write( wxT( "(kicad_pcb (version 4) (host kicad \"dummy file\") )\n" ) );
403 
404  // wxFile dtor will close the file
405  }
406 }
407 
408 
409 void KICAD_MANAGER_FRAME::OnOpenFileInTextEditor( wxCommandEvent& event )
410 {
411  // show all files in file dialog (in Kicad all files are editable texts):
412  wxString wildcard = AllFilesWildcard();
413 
414  wxString default_dir = Prj().GetProjectPath();
415 
416  wxFileDialog dlg( this, _( "Load File to Edit" ), default_dir,
417  wxEmptyString, wildcard, wxFD_OPEN );
418 
419  if( dlg.ShowModal() == wxID_CANCEL )
420  return;
421 
422  wxString filename = wxT( "\"" );
423  filename += dlg.GetPath() + wxT( "\"" );
424 
425  if( !dlg.GetPath().IsEmpty() && !Pgm().GetEditorName().IsEmpty() )
427 }
428 
429 
430 void KICAD_MANAGER_FRAME::OnBrowseInFileExplorer( wxCommandEvent& event )
431 {
432  // open project directory in host OS's file explorer
433  LaunchExternal( Prj().GetProjectPath() );
434 }
435 
436 
438 {
440 }
441 
442 
443 void KICAD_MANAGER_FRAME::language_change( wxCommandEvent& event )
444 {
445  int id = event.GetId();
446  Kiway().SetLanguage( id );
447 }
448 
449 
451 {
452  // call my base class
454 
455  // tooltips in toolbars
458 
459  PrintPrjInfo();
460 }
461 
462 
463 void KICAD_MANAGER_FRAME::CommonSettingsChanged( bool aEnvVarsChanged )
464 {
465  int historySize = Pgm().GetCommonSettings()->m_System.file_history_size;
466  PgmTop().GetFileHistory().SetMaxFiles( (unsigned) std::max( 0, historySize ) );
467 }
468 
469 
471 {
472  m_messagesBox->Clear();
473 }
474 
475 
477 {
479 
480  auto settings = dynamic_cast<KICAD_SETTINGS*>( aCfg );
481  m_leftWinWidth = settings->m_LeftWinWidth;
482 }
483 
484 
486 {
488 
489  auto settings = dynamic_cast<KICAD_SETTINGS*>( aCfg );
490  settings->m_LeftWinWidth = m_leftWin->GetSize().x;
491 }
492 
493 
495  PANEL_HOTKEYS_EDITOR* aHotkeysPanel )
496 {
497  aHotkeysPanel->AddHotKeys( GetToolManager() );
498 }
499 
500 
501 
502 
503 
505 {
506  wxString msg = wxString::Format( _( "Project name:\n%s\n" ),
508  PrintMsg( msg );
509 }
510 
511 
void ShutdownAllTools()
Shutdown all tools with a currently registered event loop in this tool manager by waking them up with...
void OnBrowseInFileExplorer(wxCommandEvent &event)
IDs used in KiCad main frame foe menuitems and tools.
VTBL_ENTRY bool PlayersClose(bool doForce)
Function PlayersClose calls the KIWAY_PLAYER::Close( bool force ) function on all the windows and if ...
Definition: kiway.cpp:414
KiCad executable names.
wxString FindValidPath(const wxString &aFileName) const
Definition: search_stack.h:73
FILE_HISTORY & GetFileHistory()
Definition: pgm_kicad.h:56
KIWAY & Kiway() const
Function Kiway returns a reference to the KIWAY that this object has an opportunity to participate in...
Definition: kiway_holder.h:56
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
void language_change(wxCommandEvent &event)
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:103
void InstallPreferences(PAGED_DIALOG *aParent, PANEL_HOTKEYS_EDITOR *aHotkeysPanel) override
Function InstallPreferences Allow a frame to load its preference panels (if any) into the preferences...
void SetMruPath(const wxString &aPath)
SEARCH_STACK & SysSearch()
Definition: pgm_kicad.h:60
This file is part of the common library TODO brief description.
virtual void SaveSettings(APP_SETTINGS_BASE *aCfg)
Saves common frame parameters to a configuration data file.
APP_SETTINGS_BASE * config() override
Returns the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
Definition: id.h:88
const std::string LegacyPcbFileExtension
const BITMAP_OPAQUE icon_kicad_xpm[1]
Definition: icon_kicad.cpp:153
void OnImportEagleFiles(wxCommandEvent &event)
Open dialog to import Eagle schematic and board files.
ACTIONS * m_actions
void OnOpenFileInTextEditor(wxCommandEvent &event)
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:139
std::vector< PARAM_CFG * > s_KicadManagerParams
void CommonSettingsChanged(bool aEnvVarsChanged) override
Notification event that some of the common (suite-wide) settings have changed.
void AddHotKeys(TOOL_MANAGER *aToolMgr)
KICAD_MANAGER_CONTROL.
SEARCH_STACK looks for files in a number of places.
Definition: search_stack.h:41
wxAuiManager m_auimgr
const std::string KiCadPcbFileExtension
VTBL_ENTRY void SetLanguage(int aLanguage)
Function SetLanguage changes the language and then calls ShowChangedLanguage() on all KIWAY_PLAYERs.
Definition: kiway.cpp:435
VTBL_ENTRY const wxString GetProjectPath() const
Function GetProjectPath returns the full path of the project.
Definition: project.cpp:102
wxString AllFilesWildcard()
void UpdateFileHistory(const wxString &FullFileName, FILE_HISTORY *aFileHistory=NULL)
Update the list of recently opened files.
VTBL_ENTRY bool ConfigLoad(const SEARCH_STACK &aSearchS, const wxString &aGroupName, const std::vector< PARAM_CFG * > &aParams, const wxString &aForeignConfigFileName=wxEmptyString)
Function ConfigLoad reads a subset of parameters from the "project" file.
Definition: project.cpp:385
void SaveSettings(APP_SETTINGS_BASE *aCfg) override
Saves common frame parameters to a configuration data file.
TOOL_MANAGER.
Definition: tool_manager.h:50
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:80
const wxString SchFileName()
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:75
void PrintMsg(const wxString &aText)
Displays aText in the text panel.
wxString GetBuildVersion()
Get the full KiCad version string.
TREE_PROJECT_FRAME Window to display the tree files.
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
wxString help_name() override
Definition of file extensions used in Kicad.
VTBL_ENTRY void ConfigSave(const SEARCH_STACK &aSList, const wxString &aGroupName, const std::vector< PARAM_CFG * > &aParams, const wxString &aFileName=wxEmptyString)
Function ConfigSave saves the current "project" parameters into the wxConfigBase* derivative.
Definition: project.cpp:350
void ReCreateTreePrj()
Create or modify the tree showing project file names.
#define KICAD_DEFAULT_DRAWFRAME_STYLE
#define PcbFileExtension
void RecreateBaseHToolbar()
(Re)Create the horizontal toolbar
VTBL_ENTRY const wxString GetProjectFullName() const
Function GetProjectFullName returns the full path and name of the project.
Definition: project.cpp:96
COMMON_CONTROL.
VTBL_ENTRY void SetProjectFullName(const wxString &aFullPathAndName)
Function SetProjectFullName sets the: 1) full directory, 2) basename, and 3) extension of the project...
Definition: project.cpp:64
Specialization of the wxAuiPaneInfo class for KiCad panels.
const std::string LegacySchematicFileExtension
void OnArchiveFiles(wxCommandEvent &event)
void SyncToolbars() override
Update the toolbars (mostly settings/check buttons/checkboxes) with the current controller state.
EVT_MENU_RANGE(ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, KICAD_MANAGER_FRAME::language_change) KICAD_MANAGER_FRAME
PGM_KICAD & PgmTop()
Definition: kicad.cpp:72
void LoadSettings(APP_SETTINGS_BASE *aCfg) override
Load common frame parameters from a configuration file.
const wxString GetProjectFileName()
void SetProjectFileName(const wxString &aFullProjectProFileName)
void OnCloseWindow(wxCloseEvent &Event)
void SetMaxFiles(size_t aMaxFiles)
Update the number of files that will be contained inside the file history.
Definition: filehistory.cpp:83
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:101
const wxString PcbLegacyFileName()
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
#define KICAD_MANAGER_FRAME_NAME
#define _(s)
Definition: 3d_actions.cpp:33
void OnSize(wxSizeEvent &event)
The base frame for deriving all KiCad main window classes.
const wxString PcbFileName()
APP_SETTINGS_BASE * PgmSettings()
Definition: pgm_kicad.h:58
static bool empty(const wxTextEntryBase *aCtrl)
void SetEnvironment(EDA_ITEM *aModel, KIGFX::VIEW *aView, KIGFX::VIEW_CONTROLS *aViewControls, EDA_BASE_FRAME *aFrame)
Sets the work environment (model, view, view controls and the parent window).
wxString GetHelpFileName()
Definition: pgm_kicad.h:62
Definition: id.h:87
KICAD_MANAGER_ACTIONS.
TOOL_MANAGER * m_toolManager
void LoadProject(const wxFileName &aProjectFileName)
void OnUnarchiveFiles(wxCommandEvent &event)
void CreateNewProject(const wxFileName &aProjectFileName)
Creates a new project by setting up and initial project, schematic, and board files.
void OnExit(wxCommandEvent &event)
void ShowChangedLanguage() override
Redraw the menus and what not in current language.
void LaunchExternal(const wxString &aPath)
Launches the given file or folder in the host OS.
Definition: launch_ext.cpp:26
const SEARCH_STACK & sys_search() override
Return a SEARCH_STACK pertaining to entire program.
void ClearMsg()
Erase the text panel.
virtual void ShowChangedLanguage()
Redraw the menus and what not in current language.
void PrintPrjInfo()
Prints the current working directory name and the projet name on the text panel.
TREE_PROJECT_FRAME * m_leftWin
The main KiCad project manager frame.
static TOOL_ACTION openTextEditor
#define GeneralGroupName
virtual void LoadSettings(APP_SETTINGS_BASE *aCfg)
Load common frame parameters from a configuration file.
KIWAY Kiway