Fix template path bugs.

Remove KICAD_PTEMPLATE environment variable as it's purpose was not
clear and was often poorly defined as the path to the KiCad installed
templates.

Add a new KICAD_TEMPLATE_DIR environment variable which clearly should
be the path of the KiCad installed templates.  Make this environment
variable available in the user settings in case the default is wrong
which has been the case in some instances.  Use the standard search
stack to set the default system template path which has a much greater
chance of being correct.

Add a new KICAD_USER_TEMPLATE_DIR environment variable which clearly
should be the path of the user defined templates.  Users most likely
were not even aware of the old default user path unless they read the
fine manual.

Set template path search stack priority as follows:

* KICAD_USER_TEMPLATE_DIR
* KICAD_TEMPLATE_DIR
* Search stack template paths

Reverse template selection dialog and project path dialog for improved
user experience.

Fixes lp:1543443

https://bugs.launchpad.net/kicad/+bug/1543443
This commit is contained in:
Wayne Stambaugh 2018-05-19 12:10:08 -04:00
parent 8badfea17a
commit 5678a166ee
4 changed files with 132 additions and 89 deletions

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2015 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2015-2017 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2015-2018 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -66,7 +66,7 @@ protected:
void OnSelectPath( wxCommandEvent& event ) override;
void onHelpClick( wxCommandEvent& event ) override;
// Currently, only upper case variable names are acepted. onVarNameChange
// Currently, only upper case variable names are accepted. onVarNameChange
// changes on the fly any lower case char by the corresponding upper case
void onVarNameChange( wxCommandEvent& event ) override;
@ -285,6 +285,7 @@ void DIALOG_ENV_VAR_CONFIG::EditSelectedEntry()
}
}
void DIALOG_ENV_VAR_CONFIG::OnHelpButton( wxCommandEvent& event )
{
wxString msg = _( "Enter the name and value for each environment variable. Grey entries "
@ -296,10 +297,12 @@ void DIALOG_ENV_VAR_CONFIG::OnHelpButton( wxCommandEvent& event )
msg << _( "To ensure environment variable names are valid on all platforms, the name field "
"will only accept upper case letters, digits, and the underscore characters." );
msg << wxT( "</b><br><br>" );
msg << _( "<b>KICAD_SYMBOL_DIR</b> is the base path of the locally installed symbol libraries." );
msg << _( "<b>KICAD_SYMBOL_DIR</b> is the base path of the locally installed symbol "
"libraries." );
msg << wxT( "<br><br>" );
msg << _( "<b>KIGITHUB</b> is used by KiCad to define the URL of the repository "
"of the official KiCad footprint libraries." );
"of the official KiCad footprint libraries. This is only required if the "
"Github plugin is used to access footprint libraries" );
msg << wxT( "<br><br>" );
msg << _( "<b>KISYS3DMOD</b> is the base path of system footprint 3D "
"shapes (.3Dshapes folders)." );
@ -313,8 +316,11 @@ void DIALOG_ENV_VAR_CONFIG::OnHelpButton( wxCommandEvent& event )
"project. For instance, ${KIPRJMOD}/libs/footprints.pretty can be defined as a "
"folder containing a project specific footprint library named footprints.pretty." );
msg << wxT( "<br><br>" );
msg << _( "<b>KICAD_PTEMPLATES</b> is optional and can be defined if you want to "
"create your own project templates folder." );
msg << _( "<b>KICAD_TEMPLATE_DIR</b> is required and is the path containing the project "
"templates installed with KiCad." );
msg << wxT( "<br><br>" );
msg << _( "<b>KICAD_USER_TEMPLATE_DIR</b> is required and is the path containing any user "
"specific project templates." );
HTML_MESSAGE_BOX dlg( GetParent(), _( "Environment Variable Help" ) );
dlg.SetDialogSizeInDU( 400, 350 );
@ -337,8 +343,9 @@ bool DIALOG_ENV_VAR_CONFIG::IsEnvVarImmutable( const wxString aEnvVar )
"KISYS3DMOD",
"KISYSMOD",
"KIPRJMOD",
"KICAD_PTEMPLATES",
"KICAD_SYMBOL_DIR"
"KICAD_SYMBOL_DIR",
"KICAD_TEMPLATE_DIR",
"KICAD_USER_TEMPLATE_DIR"
};
for( unsigned int ii=0; ii<6; ii++ )

View File

@ -2,8 +2,8 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2008-2015 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -482,6 +482,7 @@ bool PGM_BASE::InitPgm()
// KISYSMOD
envVarName = wxT( "KISYSMOD" );
if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
{
tmpFileName.AssignDir( envValue );
@ -493,11 +494,13 @@ bool PGM_BASE::InitPgm()
tmpFileName.AppendDir( wxT( "modules" ) );
envVarItem.SetDefinedExternally( false );
}
envVarItem.SetValue( tmpFileName.GetPath() );
m_local_env_vars[ envVarName ] = envVarItem;
// KISYS3DMOD
envVarName = wxT( "KISYS3DMOD" );
if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
{
tmpFileName.AssignDir( envValue );
@ -508,11 +511,13 @@ bool PGM_BASE::InitPgm()
tmpFileName.AppendDir( wxT( "packages3d" ) );
envVarItem.SetDefinedExternally( false );
}
envVarItem.SetValue( tmpFileName.GetFullPath() );
m_local_env_vars[ envVarName ] = envVarItem;
// KICAD_PTEMPLATES
envVarName = wxT( "KICAD_PTEMPLATES" );
// KICAD_TEMPLATE_DIR
envVarName = "KICAD_TEMPLATE_DIR";
if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
{
tmpFileName.AssignDir( envValue );
@ -520,15 +525,67 @@ bool PGM_BASE::InitPgm()
}
else
{
tmpFileName = baseSharePath;
tmpFileName.AppendDir( wxT( "template" ) );
// Attempt to find the best default template path.
SEARCH_STACK bases;
SEARCH_STACK templatePaths;
SystemDirsAppend( &bases );
for( unsigned i = 0; i < bases.GetCount(); ++i )
{
wxFileName fn( bases[i], wxEmptyString );
// Add KiCad template file path to search path list.
fn.AppendDir( "template" );
// Only add path if exists and can be read by the user.
if( fn.DirExists() && fn.IsDirReadable() )
{
wxLogDebug( "Checking template path '%s' exists", fn.GetPath() );
templatePaths.AddPaths( fn.GetPath() );
}
}
if( templatePaths.IsEmpty() )
{
tmpFileName = baseSharePath;
tmpFileName.AppendDir( "template" );
}
else
{
// Take the first one. There may be more but this will likely be the best option.
tmpFileName.AssignDir( templatePaths[0] );
}
envVarItem.SetDefinedExternally( false );
}
envVarItem.SetValue( tmpFileName.GetPath() );
m_local_env_vars[ envVarName ] = envVarItem;
// KICAD_USER_TEMPLATE_DIR
envVarName = "KICAD_USER_TEMPLATE_DIR";
if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
{
tmpFileName.AssignDir( envValue );
envVarItem.SetDefinedExternally( true );
}
else
{
// Default user template path.
tmpFileName = wxStandardPaths::Get().GetDocumentsDir();
tmpFileName.AppendDir( "kicad" );
tmpFileName.AppendDir( "template" );
envVarItem.SetDefinedExternally( false );
}
envVarItem.SetValue( tmpFileName.GetPath() );
m_local_env_vars[ envVarName ] = envVarItem;
// KICAD_SYMBOLS
envVarName = wxT( "KICAD_SYMBOL_DIR" );
if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
{
tmpFileName.AssignDir( envValue );
@ -540,6 +597,7 @@ bool PGM_BASE::InitPgm()
tmpFileName.AppendDir( wxT( "library" ) );
envVarItem.SetDefinedExternally( false );
}
envVarItem.SetValue( tmpFileName.GetPath() );
m_local_env_vars[ envVarName ] = envVarItem;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2004-2017 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2004-2018 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -59,6 +59,7 @@ KIFACE_I& Kiface()
throw std::logic_error( "Unexpected call to Kiface() in kicad/kicad.cpp" );
}
static PGM_KICAD program;
@ -104,8 +105,24 @@ bool PGM_KICAD::OnPgmInit()
// Add KiCad template file path to search path list.
fn.AppendDir( wxT( "template" ) );
m_bm.m_search.AddPaths( fn.GetPath() );
// Only add path if exists and can be read by the user.
if( fn.DirExists() && fn.IsDirReadable() )
m_bm.m_search.AddPaths( fn.GetPath() );
}
// The KICAD_TEMPLATE_DIR takes precedence over the search stack template path.
ENV_VAR_MAP_CITER it = GetLocalEnvVariables().find( "KICAD_TEMPLATE_DIR" );
if( it != GetLocalEnvVariables().end() && it->second.GetValue() != wxEmptyString )
m_bm.m_search.Insert( it->second.GetValue(), 0 );
// The KICAD_USER_TEMPLATE_DIR takes precedence over KICAD_TEMPLATE_DIR and the search
// stack template path.
it = GetLocalEnvVariables().find( "KICAD_USER_TEMPLATE_DIR" );
if( it != GetLocalEnvVariables().end() && it->second.GetValue() != wxEmptyString )
m_bm.m_search.Insert( it->second.GetValue(), 0 );
}
// Must be called before creating the main frame in order to
@ -203,8 +220,9 @@ struct APP_KICAD : public wxApp
#if defined (__LINUX__)
APP_KICAD(): wxApp()
{
// Disable proxy menu in Unity window manager. Only usual menubar works with wxWidgets (at least <= 3.1)
// When the proxy menu menubar is enable, some important things for us do not work: menuitems UI events and shortcuts.
// Disable proxy menu in Unity window manager. Only usual menubar works with
// wxWidgets (at least <= 3.1). When the proxy menu menubar is enable, some
// important things for us do not work: menuitems UI events and shortcuts.
wxString wm;
if( wxGetEnv( wxT( "XDG_CURRENT_DESKTOP" ), &wm ) && wm.CmpNoCase( wxT( "Unity" ) ) == 0 )
@ -251,9 +269,8 @@ struct APP_KICAD : public wxApp
}
/**
* Function MacOpenFile
* is specific to MacOSX (not used under Linux or Windows).
* MacOSX requires it for file association.
* Set MacOS file associations.
*
* @see http://wiki.wxwidgets.org/WxMac-specific_topics
*/
void MacOpenFile( const wxString& aFileName )

View File

@ -270,82 +270,27 @@ void KICAD_MANAGER_FRAME::OnNewProject( wxCommandEvent& aEvent )
void KICAD_MANAGER_FRAME::OnCreateProjectFromTemplate( wxCommandEvent& event )
{
wxString default_dir = wxFileName( Prj().GetProjectFullName() ).GetPathWithSep();
wxString title = _( "New Project Folder" );
wxDirDialog dlg( this, title, default_dir );
if( dlg.ShowModal() == wxID_CANCEL )
return;
// Builds the project .pro filename, from the new project folder name
wxFileName fn;
fn.AssignDir( dlg.GetPath() );
fn.SetName( dlg.GetPath().AfterLast( SEP() ) );
fn.SetExt( wxT( "pro" ) );
wxChar sep[2] = { SEP(), 0 }; // nul terminated separator wxChar string.
ClearMsg();
DIALOG_TEMPLATE_SELECTOR* ps = new DIALOG_TEMPLATE_SELECTOR( this );
wxFileName templatePath;
wxString envStr;
#ifndef __WXMAC__
wxGetEnv( wxT( "KICAD" ), &envStr );
// KiCad system template path.
ENV_VAR_MAP_CITER it = Pgm().GetLocalEnvVariables().find( "KICAD_TEMPLATE_DIR" );
// Add a new tab for system templates
if( !envStr.empty() )
if( it != Pgm().GetLocalEnvVariables().end() && it->second.GetValue() != wxEmptyString )
{
// user may or may not have including terminating separator.
if( !envStr.EndsWith( sep ) )
envStr += sep;
templatePath = envStr + wxT( "template" ) + sep;
templatePath.AssignDir( it->second.GetValue() );
ps->AddTemplatesPage( _( "System Templates" ), templatePath );
}
else
// User template path.
it = Pgm().GetLocalEnvVariables().find( "KICAD_USER_TEMPLATE_DIR" );
if( it != Pgm().GetLocalEnvVariables().end() && it->second.GetValue() != wxEmptyString )
{
// The standard path should be in the share directory for kicad. As
// it is normal on Windows to only have the share directory and not
// the kicad sub-directory we fall back to that if the directory
// doesn't exist
templatePath = wxPathOnly( wxStandardPaths::Get().GetExecutablePath() ) +
sep + wxT( ".." ) + sep + wxT( "share" ) + sep + wxT( "kicad" ) +
sep + wxT( "template" ) + sep;
if( !wxDirExists( templatePath.GetFullPath() ) )
{
templatePath = wxPathOnly( wxStandardPaths::Get().GetExecutablePath() ) + sep +
wxT( ".." ) + sep + wxT( "share" ) + sep + wxT( "template" ) + sep;
}
}
#else
// Use what is provided in the bundle data dir
templatePath = GetOSXKicadDataDir() + sep + wxT( "template" );
#endif
ps->AddTemplatesPage( _( "System Templates" ), templatePath );
// Add a new tab for user templates
wxFileName userPath = wxStandardPaths::Get().GetDocumentsDir() + sep + wxT( "kicad" ) +
sep + wxT( "template" ) + sep;
ps->AddTemplatesPage( _( "User Templates" ), userPath );
// Check to see if a custom template location is available and setup a
// new selection tab if there is.
envStr.clear();
wxGetEnv( wxT( "KICAD_PTEMPLATES" ), &envStr );
if( !envStr.empty() )
{
if( !envStr.EndsWith( sep ) )
envStr += sep;
wxFileName envPath = envStr;
ps->AddTemplatesPage( _( "Portable Templates" ), envPath );
templatePath.AssignDir( it->second.GetValue() );
ps->AddTemplatesPage( _( "User Templates" ), templatePath );
}
// Show the project template selector dialog
@ -362,7 +307,21 @@ void KICAD_MANAGER_FRAME::OnCreateProjectFromTemplate( wxCommandEvent& event )
return;
}
// Make sure the user has write permissions to the base path.
// Get project destination folder and project file name.
wxString default_dir = wxFileName( Prj().GetProjectFullName() ).GetPathWithSep();
wxString title = _( "New Project Folder" );
wxDirDialog dlg( this, title, default_dir );
if( dlg.ShowModal() == wxID_CANCEL )
return;
// Builds the project .pro filename, from the new project folder name
wxFileName fn;
fn.AssignDir( dlg.GetPath() );
fn.SetName( dlg.GetPath().AfterLast( SEP() ) );
fn.SetExt( "pro" );
// Make sure the user has write permissions to the project path.
wxFileName prjPath = fn;
while( !prjPath.DirExists() )
@ -380,6 +339,8 @@ void KICAD_MANAGER_FRAME::OnCreateProjectFromTemplate( wxCommandEvent& event )
return;
}
ClearMsg();
// Make sure we are not overwriting anything in the destination folder.
std::vector< wxFileName > destFiles;