1 
2 ///////////////////////////////////////////////////////////
3 //                                                       //
4 //                         SAGA                          //
5 //                                                       //
6 //      System for Automated Geoscientific Analyses      //
7 //                                                       //
8 //                Command Line Interface                 //
9 //                                                       //
10 //                   Program: SAGA_CMD                   //
11 //                                                       //
12 //-------------------------------------------------------//
13 //                                                       //
14 //                      config.cpp                       //
15 //                                                       //
16 //          Copyright (C) 2017 by Olaf Conrad            //
17 //                                                       //
18 //-------------------------------------------------------//
19 //                                                       //
20 // This file is part of 'SAGA - System for Automated     //
21 // Geoscientific Analyses'. SAGA is free software; you   //
22 // can redistribute it and/or modify it under the terms  //
23 // of the GNU General Public License as published by the //
24 // Free Software Foundation, either version 2 of the     //
25 // License, or (at your option) any later version.       //
26 //                                                       //
27 // SAGA is distributed in the hope that it will be       //
28 // useful, but WITHOUT ANY WARRANTY; without even the    //
29 // implied warranty of MERCHANTABILITY or FITNESS FOR A  //
30 // PARTICULAR PURPOSE. See the GNU General Public        //
31 // License for more details.                             //
32 //                                                       //
33 // You should have received a copy of the GNU Lesser     //
34 // General Public License along with this program; if    //
35 // not, see <http://www.gnu.org/licenses/>.              //
36 //                                                       //
37 //-------------------------------------------------------//
38 //                                                       //
39 //    contact:    Olaf Conrad                            //
40 //                Institute of Geography                 //
41 //                University of Hamburg                  //
42 //                Germany                                //
43 //                                                       //
44 //    e-mail:     oconrad@saga-gis.org                   //
45 //                                                       //
46 ///////////////////////////////////////////////////////////
47 
48 //---------------------------------------------------------
49 #include "config.h"
50 #include "callback.h"
51 
52 //---------------------------------------------------------
53 #include <wx/config.h>
54 #include <wx/fileconf.h>
55 #include <wx/wfstream.h>
56 #include <wx/stdpaths.h>
57 #include <wx/utils.h>
58 #include <wx/app.h>
59 
60 
61 ///////////////////////////////////////////////////////////
62 //                                                       //
63 //                                                       //
64 //                                                       //
65 ///////////////////////////////////////////////////////////
66 
67 //---------------------------------------------------------
Config_Read(wxConfigBase * pConfig,const wxString & Group,const wxString & Key,bool & Value)68 bool	Config_Read(wxConfigBase *pConfig, const wxString &Group, const wxString &Key, bool &Value)
69 {
70 	pConfig->SetPath("/" + Group);	return( pConfig->Read(Key, &Value) );
71 }
72 
Config_Read(wxConfigBase * pConfig,const wxString & Group,const wxString & Key,int & Value)73 bool	Config_Read(wxConfigBase *pConfig, const wxString &Group, const wxString &Key, int &Value)
74 {
75 	pConfig->SetPath("/" + Group);	return( pConfig->Read(Key, &Value) );
76 }
77 
Config_Read(wxConfigBase * pConfig,const wxString & Group,const wxString & Key,double & Value)78 bool	Config_Read(wxConfigBase *pConfig, const wxString &Group, const wxString &Key, double &Value)
79 {
80 	pConfig->SetPath("/" + Group);	return( pConfig->Read(Key, &Value) );
81 }
82 
Config_Read(wxConfigBase * pConfig,const wxString & Group,const wxString & Key,wxString & Value)83 bool	Config_Read(wxConfigBase *pConfig, const wxString &Group, const wxString &Key, wxString &Value)
84 {
85 	pConfig->SetPath("/" + Group);	return( pConfig->Read(Key, &Value) );
86 }
87 
88 //---------------------------------------------------------
Config_Write(wxConfigBase * pConfig,const wxString & Group,const wxString & Key,bool Value)89 bool	Config_Write(wxConfigBase *pConfig, const wxString &Group, const wxString &Key, bool Value)
90 {
91 	pConfig->SetPath("/" + Group);	return( pConfig->Write(Key, Value) ? pConfig->Flush() : false );
92 }
93 
Config_Write(wxConfigBase * pConfig,const wxString & Group,const wxString & Key,int Value)94 bool	Config_Write(wxConfigBase *pConfig, const wxString &Group, const wxString &Key, int Value)
95 {
96 	pConfig->SetPath("/" + Group);	return( pConfig->Write(Key, Value) ? pConfig->Flush() : false );
97 }
98 
Config_Write(wxConfigBase * pConfig,const wxString & Group,const wxString & Key,double Value)99 bool	Config_Write(wxConfigBase *pConfig, const wxString &Group, const wxString &Key, double Value)
100 {
101 	pConfig->SetPath("/" + Group);	return( pConfig->Write(Key, Value) ? pConfig->Flush() : false );
102 }
103 
Config_Write(wxConfigBase * pConfig,const wxString & Group,const wxString & Key,const wxString & Value)104 bool	Config_Write(wxConfigBase *pConfig, const wxString &Group, const wxString &Key, const wxString &Value)
105 {
106 	pConfig->SetPath("/" + Group);	return( pConfig->Write(Key, Value) ? pConfig->Flush() : false );
107 }
108 
Config_Write(wxConfigBase * pConfig,const wxString & Group,const wxString & Key,const SG_Char * Value)109 bool	Config_Write(wxConfigBase *pConfig, const wxString &Group, const wxString &Key, const SG_Char *Value)
110 {
111 	pConfig->SetPath("/" + Group);	return( pConfig->Write(Key, Value) ? pConfig->Flush() : false );
112 }
113 
114 
115 ///////////////////////////////////////////////////////////
116 //                                                       //
117 ///////////////////////////////////////////////////////////
118 
119 //---------------------------------------------------------
Config_Create(wxConfigBase * pConfig)120 bool	Config_Create	(wxConfigBase *pConfig)
121 {
122 	Config_Write(pConfig,   "CMD", "NO_PROGRESS"         , false   );	// q, s: no progress report
123 	Config_Write(pConfig,   "CMD", "NO_MESSAGES"         , false   );	// r, s: no messages report
124 	Config_Write(pConfig,   "CMD", "INTERACTIVE"         , false   );	// i: allow user interaction
125 	Config_Write(pConfig,   "CMD", "XML_MESSAGE"         , false   );	// x: message output as xml
126 
127 	Config_Write(pConfig, "TOOLS", "LNG_FILE_DIC"        , SG_T(""));	// translation dictionary
128 	Config_Write(pConfig, "TOOLS", "PROJECTIONS"         , false   );	// load projections dictionary
129 	Config_Write(pConfig, "TOOLS", "OMP_THREADS_MAX"     , SG_OMP_Get_Max_Num_Procs());
130 	Config_Write(pConfig, "TOOLS", "ADD_LIB_PATHS"       , SG_T(""));	// additional tool library paths (aka SAGA_TLB)
131 
132 	Config_Write(pConfig,  "DATA", "GRID_CACHE_TMPDIR"   , SG_Grid_Cache_Get_Directory   ());
133 	Config_Write(pConfig,  "DATA", "GRID_CACHE_MODE"     , SG_Grid_Cache_Get_Mode        ());
134 	Config_Write(pConfig,  "DATA", "GRID_CACHE_THRESHLOD", SG_Grid_Cache_Get_Threshold_MB());
135 	Config_Write(pConfig,  "DATA", "GRID_COORD_PRECISION", CSG_Grid_System::Get_Precision());
136 	Config_Write(pConfig,  "DATA", "HISTORY_DEPTH"       , SG_Get_History_Depth());
137 	Config_Write(pConfig,  "DATA", "HISTORY_LISTS"       , SG_Get_History_Ignore_Lists() != 0);
138 
139 	return( true );
140 }
141 
142 //---------------------------------------------------------
Config_Load(wxConfigBase * pConfig)143 bool	Config_Load		(wxConfigBase *pConfig)
144 {
145 #if   defined(_SAGA_LINUX)
146 	CSG_String	Path_Shared	= SHARE_PATH;
147 #elif defined(_SAGA_MSW)
148 	CSG_String	Path_Shared	= SG_UI_Get_Application_Path(true);
149 #endif
150 
151 	bool bValue; int iValue; double dValue; wxString sValue;
152 
153 	//-----------------------------------------------------
154 	Config_Read(pConfig, "CMD", "NO_PROGRESS", bValue = false); CMD_Set_Show_Progress(bValue == false);	// q, s: no progress report
155 	Config_Read(pConfig, "CMD", "NO_MESSAGES", bValue = false); CMD_Set_Show_Messages(bValue == false);	// r, s: no messages report
156 	Config_Read(pConfig, "CMD", "INTERACTIVE", bValue = false); CMD_Set_Interactive  (bValue ==  true);	// i: allow user interaction
157 	Config_Read(pConfig, "CMD", "XML_MESSAGE", bValue = false); CMD_Set_XML          (bValue ==  true);	// x: message output as xml
158 
159 	//-----------------------------------------------------
160 	if( Config_Read(pConfig, "TOOLS", "LNG_FILE_DIC", sValue) && wxFileExists(sValue) )	// load translation dictionary
161 	{
162 		SG_Printf("\n%s:", _TL("loading translation dictionary"));
163 		SG_Printf("\n%s.\n",
164 		//	SG_Get_Translator().Create(SG_File_Make_Path(Path_Shared, SG_T("saga"), SG_T("lng")), false)
165 			SG_Get_Translator().Create(&sValue, false)
166 			? _TL("success") : _TL("failed")
167 		);
168 	}
169 
170 	if( Config_Read(pConfig, "TOOLS", "OMP_THREADS_MAX"     , iValue) )	{	SG_OMP_Set_Max_Num_Threads(iValue);	}
171 
172 	if( Config_Read(pConfig, "TOOLS", "ADD_LIB_PATHS"       , sValue) && !sValue.IsEmpty() )
173 	{
174 		wxString	Path;
175 
176 		if( (wxGetEnv("SAGA_TLB", &Path) || wxGetEnv("SAGA_MLB", &Path)) && !Path.IsEmpty() )
177 		{
178 			sValue	+= ";" + Path;
179 		}
180 
181 		wxSetEnv("SAGA_TLB", sValue);
182 	}
183 
184 	//-----------------------------------------------------
185 	if( Config_Read(pConfig,  "DATA", "GRID_CACHE_TMPDIR"   , sValue) )	{	SG_Grid_Cache_Set_Directory   (sValue);	}
186 	if( Config_Read(pConfig,  "DATA", "GRID_CACHE_MODE"     , iValue) )	{	SG_Grid_Cache_Set_Mode        (iValue);	}
187 	if( Config_Read(pConfig,  "DATA", "GRID_CACHE_THRESHLOD", dValue) )	{	SG_Grid_Cache_Set_Threshold_MB(dValue);	}
188 
189 	if( Config_Read(pConfig,  "DATA", "GRID_COORD_PRECISION", iValue) )	{	CSG_Grid_System::Set_Precision(iValue);	}
190 
191 	if( Config_Read(pConfig,  "DATA", "HISTORY_DEPTH"       , iValue) )	{	SG_Set_History_Depth       (iValue     );	}
192 	if( Config_Read(pConfig,  "DATA", "HISTORY_LISTS"       , iValue) )	{	SG_Set_History_Ignore_Lists(iValue != 0);	}
193 
194 	//-----------------------------------------------------
195 	return( true );
196 }
197 
198 
199 ///////////////////////////////////////////////////////////
200 //                                                       //
201 ///////////////////////////////////////////////////////////
202 
203 //---------------------------------------------------------
Config_Default(bool bCreate)204 wxConfigBase *	Config_Default(bool bCreate)
205 {
206 #if defined(_SAGA_MSW)
207 	wxFileName	fLocal(SG_UI_Get_Application_Path(false).c_str()); fLocal.SetExt("ini");
208 
209 	if( !fLocal.FileExists() && !bCreate )
210 	{
211 		return( NULL );
212 	}
213 
214 	if( ( fLocal.FileExists() && (!fLocal.IsFileReadable() || !fLocal.IsFileWritable()))
215 	||  (!fLocal.FileExists() && (!fLocal.IsDirReadable () || !fLocal.IsDirWritable ())) )
216 	{
217 		wxFileName	fUser (wxGetHomeDir(), "saga_cmd", "ini");
218 	//	wxFileName	fUser (wxStandardPaths::Get().GetUserConfigDir(), "saga_cmd", "ini");
219 
220 		if(	fLocal.FileExists() && fLocal.IsFileReadable() && !fUser.FileExists() )	// create a copy in user's home directory
221 		{
222 			wxFileInputStream	is(fLocal.GetFullPath());
223 			wxFileOutputStream	os(fUser .GetFullPath());
224 			wxFileConfig		ic(is);	ic.Save(os);
225 		}
226 
227 		fLocal	= fUser;
228 	}
229 
230 	if( (fLocal.FileExists() && fLocal.IsFileWritable()) || (!fLocal.FileExists() && fLocal.IsDirWritable()) )
231 	{
232 		return( new wxFileConfig(wxEmptyString, wxEmptyString, fLocal.GetFullPath(), fLocal.GetFullPath(), wxCONFIG_USE_LOCAL_FILE|wxCONFIG_USE_GLOBAL_FILE|wxCONFIG_USE_RELATIVE_PATH) );
233 	}
234 #endif
235 
236 	return( new wxConfig );	// this might go to registry
237 }
238 
239 //---------------------------------------------------------
Config_Load(void)240 bool	Config_Load		(void)
241 {
242 	wxConfigBase	*pConfig	= Config_Default(false);
243 
244 	if( pConfig )
245 	{
246 		Config_Load(pConfig);
247 
248 		delete(pConfig);
249 
250 		return( true );
251 	}
252 
253 	return( false );
254 }
255 
256 //---------------------------------------------------------
Config_Load(const CSG_String & File)257 bool	Config_Load		(const CSG_String &File)
258 {
259 	if( !SG_File_Exists(File) )
260 	{
261 		return( false );
262 	}
263 
264 	wxConfigBase	*pConfig	= new wxFileConfig(wxEmptyString, wxEmptyString, File.c_str(), File.c_str(), wxCONFIG_USE_LOCAL_FILE|wxCONFIG_USE_GLOBAL_FILE|wxCONFIG_USE_RELATIVE_PATH);
265 
266 	Config_Load(pConfig);
267 
268 	delete(pConfig);
269 
270 	return( true );
271 }
272 
273 
274 //---------------------------------------------------------
Config_Create(const CSG_String & File)275 bool	Config_Create	(const CSG_String &File)
276 {
277 	wxConfigBase	*pConfig;
278 
279 	if( File.is_Empty() )
280 	{
281 		SG_Printf(CSG_String::Format("\n%s...", _TL("creating default configuration")));
282 
283 		pConfig	= Config_Default(true);
284 	}
285 	else
286 	{
287 		SG_Printf(CSG_String::Format("\n%s\n>>%s\n...", _TL("creating default configuration"), File.c_str()));
288 
289 		pConfig	= new wxFileConfig(wxEmptyString, wxEmptyString, File.c_str(), File.c_str(), wxCONFIG_USE_LOCAL_FILE|wxCONFIG_USE_GLOBAL_FILE|wxCONFIG_USE_RELATIVE_PATH);
290 	}
291 
292 	Config_Create(pConfig);
293 
294 	delete(pConfig);
295 
296 	SG_Printf(CSG_String::Format("%s\n", _TL("ready")));
297 
298 	return( true );
299 }
300 
301 
302 ///////////////////////////////////////////////////////////
303 //                                                       //
304 //                                                       //
305 //                                                       //
306 ///////////////////////////////////////////////////////////
307 
308 //---------------------------------------------------------
309