1 /* massXpert - the true massist's program.
2    --------------------------------------
3    Copyright(C) 2006,2007 Filippo Rusconi
4 
5    http://www.massxpert.org/massXpert
6 
7    This file is part of the massXpert project.
8 
9    The massxpert project is the successor to the "GNU polyxmass"
10    project that is an official GNU project package(see
11    www.gnu.org). The massXpert project is not endorsed by the GNU
12    project, although it is released ---in its entirety--- under the
13    GNU General Public License. A huge part of the code in massXpert
14    is actually a C++ rewrite of code in GNU polyxmass. As such
15    massXpert was started at the Centre National de la Recherche
16    Scientifique(FRANCE), that granted me the formal authorization to
17    publish it under this Free Software License.
18 
19    This software is free software; you can redistribute it and/or
20    modify it under the terms of the GNU  General Public
21    License version 3, as published by the Free Software Foundation.
22 
23 
24    This software is distributed in the hope that it will be useful,
25    but WITHOUT ANY WARRANTY; without even the implied warranty of
26    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
27    General Public License for more details.
28 
29    You should have received a copy of the GNU General Public License
30    along with this software; if not, write to the
31 
32    Free Software Foundation, Inc.,
33 
34    51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
35 */
36 
37 
38 /////////////////////// Qt includes
39 #include <QApplication>
40 #include <QDir>
41 #include <QDebug>
42 
43 #ifdef Q_WS_MAC
44 #include <CoreFoundation/CoreFoundation.h>
45 #endif
46 
47 /////////////////////// Local includes
48 #include "config.h"
49 #include "configSettings.hpp"
50 
51 
52 
53 namespace massXpert
54 {
55 
56   //! Initializes the members of the class.
57   /*! The initialization of the members of the class involves
58     determining where the system and user configuration directories are
59     located.
60 
61     \li System configuration directory: it is set by the variable
62     MASSXPERT_DATA_DIR in the config.h file. Thus, this directory is set
63     at compile time.
64 
65     \li User configuration directory: it is determined at run time by
66     inspecting the value returned by the call to QDir::homePath
67    (). Under Windows this function will return the directory of the
68     current user's profile. Typically, this is: "C:\\Documents and
69     Settings\\Username". Under non-Windows operating systems the HOME
70     environment variable is used if it exists, otherwise the path
71     returned by the rootPath() function is used(this latter function
72     returns '/' on non-Windows systems and "c:\\" on Windows).
73 
74     Inside the User/System configuration directories a "pol-chem-defs"
75     directory will contain a number of files:
76 
77     \li \c massxpert-pol-chem-defs-cat is a catalogue that relates
78     polymer chemistry definition names with the corresponding
79     directories where the definition data are to be found. For example,
80     one line from that file might be:
81 
82     protein=/home/rusconi/.massxpert/pol-chem-defs/protein/protein.xml
83 
84     This line tells that the "protein" polymer chemistry definition file
85     is named protein.xml and that it is located, along with all the
86     other data files pertaining to that same polymer chemistry
87     definition, in the /home/rusconi/.massxpert/pol-chem-defs/protein
88     directory.
89 
90     During initialization, if system configuration directories are not
91     found, then these are not created. Which is not the case for the
92     user configuration directories: if these are not found, they are
93     created, thus yielding ---on a UNIX-like system for example--- the
94     following directories:
95 
96     $HOME/.massxpert and $HOME/.massxpert/pol-chem-defs
97 
98     The user might then populate these directories with data suiting her
99     needs.
100 
101     \return true if initialization was successful, false otherwise.
102   */
103   bool
initializeSystemConfig()104   ConfigSettings::initializeSystemConfig()
105   {
106     QDir dir;
107 
108     // First off, some general concepts.
109 
110     // When the software is built, a configuration process will
111     // provide values for a number of #defined variables, depending on
112     // the platform on which the software is built.
113 
114     // For example on MS-Windows, the following variables are defined:
115 
116     /*
117       #define MASSXPERT_BIN_DIR C:/Program Files/massxpert
118       #define MASSXPERT_DATA_DIR C:/Program Files/massxpert/data
119       #define MASSXPERT_LOCALE_DIR C:/Program Files/massxpert/locales
120       #define MASSXPERT_USERMAN_DIR C:/Program Files/massxpert/doc/usermanual
121 
122     */
123 
124     // On GNU/Linux, instead, the following variables are defined:
125 
126     /*
127       #define MASSXPERT_BIN_DIR /usr/local/bin
128       #define MASSXPERT_DATA_DIR /usr/local/share/massxpert
129       #define MASSXPERT_LOCALE_DIR /usr/local/share/massxpert/locales
130       #define MASSXPERT_USERMAN_DIR: /usr/local/share/doc/massxpert/usermanual
131     */
132 
133     /* On Mac OS X, instead, the software is built using not cmake,
134        but qmake, and that makes it buildable using Xcode. The build
135        generates in this case a Mac Bundle massXpert.app, which
136        installs anywhere as long as its internal structure is
137        conserved. There is an API to identify from which location the
138        bundle is used(double-clicking onto the massXpert.app
139        icon). We use that API to get the bundle directory, which might
140        be something like /Applications/massXpert.app if the bundle was
141        dropped into /Applications.
142     */
143 
144 #if defined(Q_WS_MAC)
145     CFURLRef bundleRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
146 
147     CFStringRef macPath =
148       CFURLCopyFileSystemPath(bundleRef, kCFURLPOSIXPathStyle);
149 
150     QString bundleDir =
151       CFStringGetCStringPtr(macPath, CFStringGetSystemEncoding());
152 
153     CFRelease(bundleRef);
154     CFRelease(macPath);
155 #endif
156 
157 
158     // Now, it might be of interest for the user to install the
159     // software in another location than the canonical one. In this
160     // case, the program should still be able to access the data.
161 
162     // This is what this function is for. This function will try to
163     // establish if the data that were built along the software
164     // package are actually located in the cnaonical places listed
165     // above. If not, this function returns false. The caller might
166     // then take actions to let the user manually instruct the program
167     // of where the data are located.
168 
169     // All this procedure is setup so as to let the user install the
170     // software wherever she wants.
171 
172 
173       /////////////////// MASSXPERT_DATA_DIR ///////////////////
174       /////////////////// MASSXPERT_DATA_DIR ///////////////////
175       /////////////////// MASSXPERT_DATA_DIR ///////////////////
176 
177 #ifdef Q_WS_MAC
178     dir.setPath(bundleDir + QDir::separator() + "Contents" +
179 		 QDir::separator() + "Resources" +
180 		 QDir::separator() + "data");
181 #else
182     dir.setPath(QString(MASSXPERT_DATA_DIR));
183 #endif
184 
185     // The path must be absolute and must exist.
186 
187     if (!dir.isAbsolute())
188       return false;
189 
190     if (!dir.exists())
191       return false;
192 
193     m_systemDataDir = dir.absolutePath();
194 
195     // OK, the directory exists, we still have to make sure that we
196     // can find the proper data in it. Namely the directory where the
197     // data are acutally stored(pol-chem-defs subdirectory).
198 
199     dir.setPath(dir.absolutePath() +
200 		 QDir::separator() + "pol-chem-defs");
201 
202     if (!dir.exists())
203       return false;
204 
205     m_systemPolChemDefCatDir = dir.absolutePath();
206 
207     // Finally, make sure the system catalogue file of all the polymer
208     // chemistry definitions shipped in the program package, that sits
209     // in the "pol-chem-defs" directory.
210 
211     QString filePath = dir.absolutePath() +
212       QDir::separator() + "massxpert-pol-chem-defs-cat";
213 
214     if (!QFile::exists(filePath))
215       return false;
216 
217 
218 
219 
220     /////////////////// MASSXPERT_LOCALE_DIR ///////////////////
221     /////////////////// MASSXPERT_LOCALE_DIR ///////////////////
222     /////////////////// MASSXPERT_LOCALE_DIR ///////////////////
223 
224 #ifdef Q_WS_MAC
225     dir.setPath(bundleDir + QDir::separator() + "Contents" +
226 		 QDir::separator() + "Locales");
227 #else
228     dir.setPath(QString(MASSXPERT_LOCALE_DIR));
229 #endif
230 
231     // The path must be absolute and must exist.
232 
233     if (!dir.isAbsolute())
234       return false;
235 
236     if (!dir.exists())
237       return false;
238 
239     // At the moment there is the french translation: massxpert_fr.qm
240 
241     filePath = QString(dir.absolutePath() +
242 			QDir::separator() +
243 			"massxpert_fr.qm");
244 
245     if (!QFile::exists(filePath))
246       return false;
247 
248     m_systemLocalizationDir = dir.absolutePath();
249     return true;
250   }
251 
252 
253   bool
initializeUserConfig()254   ConfigSettings::initializeUserConfig()
255   {
256     QDir dir;
257 
258 
259     // First off, some general concepts.
260 
261     // massXpert should let the user define any polymer chemistry of
262     // his requirement, without needing the root priviledges for
263     // installation of these new data.
264 
265     // This is why massXpert allows for personal data directories
266     // modelled on the same filesystem scheme as for the system data
267     // directory.
268 
269     // When the program is run, it check if the .massxpert directory
270     // exists in the home directory of the user running the
271     // program. If that directory does not exist, it is created, along
272     // with its pol-chem-defs directory.
273 
274     // On MS-Windows sytems, the home directory is located at:
275 
276     // C:\Documents and Settings\username
277 
278     // On GNU/Linux and UNIX-based systems, the home directory is:
279 
280     // /home/username
281 
282     // Thus, respectively, the user has at its disposal the following
283     // personal user data directories:
284 
285     // C:\Documents and Settings\username\.massxpert\pol-chem-defs
286 
287     // and
288 
289     // /home/username/.massxpert/pol-chem-defs
290 
291 
292     // Get the absolute directory path to user's data directory.
293 
294     dir.setPath(QDir::homePath() + QDir::separator() + ".massxpert");
295 
296     // Now make some checks: if this directory does not exist, we have
297     // to create it.
298     if (!dir.exists())
299       {
300 	if(!dir.mkpath(dir.absolutePath()))
301 	  {
302 	    qWarning() << __FILE__ << __LINE__
303 		       << "Directory" << dir.absolutePath()
304 		       << "does not exist, but its creation failed.";
305 
306 	    return false;
307 	  }
308 	else
309 	  {
310 // 	    qWarning() << __FILE__ << __LINE__
311 // 			<< "Creation of "
312 // 			<< dir.absolutePath()
313 // 			<< "succeeded.";
314 	  }
315       }
316 
317     m_userDataDir = dir.absolutePath();
318 
319     dir.setPath(m_userDataDir + QDir::separator() + "pol-chem-defs");
320 
321     if (!dir.exists())
322       {
323 	if(!dir.mkpath(dir.absolutePath()))
324 	  {
325 	    qWarning() << __FILE__ << __LINE__
326 		       << "Directory" << dir.absolutePath()
327 		       << "does not exist, but its creation failed.";
328 
329 	    return false;
330 	  }
331 	else
332 	  {
333 // 	    qWarning() << __FILE__ << __LINE__
334 // 			<< "Creation of "
335 // 			<< dir.absolutePath()
336 // 			<< "succeeded.";
337 	  }
338       }
339 
340     m_userPolChemDefCatDir = dir.absolutePath();
341 
342     return true;
343   }
344 
345 
346   //! Sets the system data directory path.
347   /*! Sets the system data directory path to the string passed
348     as argument.
349 
350     \param config string holding the new system data directory
351     path.
352   */
353   void
setSystemDataDir(const QString & config)354   ConfigSettings::setSystemDataDir(const QString &config)
355   {
356     m_systemDataDir = config;
357   }
358 
359   //! Returns the system data directory path.
360   /*!
361 
362     \return a constant reference to the system data directory
363     member data.
364   */
365   const QString &
systemDataDir() const366   ConfigSettings::systemDataDir() const
367   {
368     return m_systemDataDir;
369   }
370 
371 
372   void
setSystemLocalizationDir(const QString & config)373   ConfigSettings::setSystemLocalizationDir(const QString &config)
374   {
375     m_systemLocalizationDir = config;
376   }
377 
378 
379   const QString &
systemLocalizationDir() const380   ConfigSettings::systemLocalizationDir() const
381   {
382     return m_systemLocalizationDir;
383   }
384 
385 
386   //! Sets the user manual directory path.
387   /*! Sets the user manual directory path to the string passed
388     as argument.
389 
390     \param config string holding the new user manual directory
391     path.
392   */
393   void
setUserManDir(const QString & config)394   ConfigSettings::setUserManDir(const QString &config)
395   {
396     m_userManDir = config;
397   }
398 
399   //! Returns the user manual directory path.
400   /*!
401 
402     \return a constant reference to the user manual directory
403     member data.
404   */
405   const QString &
userManDir() const406   ConfigSettings::userManDir() const
407   {
408     return m_userManDir;
409   }
410 
411 
412   //! Sets the user data directory path.
413   /*! Sets the user data directory path to the string passed as
414     argument.
415 
416     \param config string holding the new user data directory
417     path.
418   */
419   void
setUserDataDir(const QString & config)420   ConfigSettings::setUserDataDir(const QString &config)
421   {
422     m_userDataDir = config;
423   }
424 
425 
426   //! Returns the user configuration directory path.
427   /*!
428 
429     \return a constant reference to the user configuration directory
430     member data.
431   */
432   const QString &
userDataDir() const433   ConfigSettings::userDataDir() const
434   {
435     return m_userDataDir;
436   }
437 
438 
439   //! Sets a system configuration directory path.
440   /*! Sets the system configuration directory path where the polymer
441     chemistry definition catalogues are stored.
442 
443     \param config string holding the configuration directory path.
444   */
445   void
setSystemPolChemDefCatDir(const QString & config)446   ConfigSettings::setSystemPolChemDefCatDir(const QString &config)
447   {
448     m_systemPolChemDefCatDir = config;
449   }
450 
451 
452   //! Returns a configuration directory path.
453   /*! Returns the system configuration directory path where the polymer
454     chemistry definition catalogues are stored.
455 
456     \return a constant reference to the configuration directory member
457     data.
458   */
459   const QString &
systemPolChemDefCatDir() const460   ConfigSettings::systemPolChemDefCatDir() const
461   {
462     return m_systemPolChemDefCatDir;
463   }
464 
465 
466   //! Sets a user configuration directory path.
467   /*! Sets the user configuration directory path where the polymer
468     chemistry definition catalogues are stored.
469 
470     \param config string holding the configuration directory path.
471   */
472   void
setUserPolChemDefCatDir(const QString & config)473   ConfigSettings::setUserPolChemDefCatDir(const QString &config)
474   {
475     m_userPolChemDefCatDir = config;
476   }
477 
478 
479   //! Returns a configuration directory path.
480   /*! Returns the user configuration directory path where the polymer
481     chemistry definition catalogues are stored.
482 
483     \return a constant reference to the configuration directory member
484     data.
485   */
486   const QString &
userPolChemDefCatDir() const487   ConfigSettings::userPolChemDefCatDir() const
488   {
489     return m_userPolChemDefCatDir;
490   }
491 
492 } // namespace massXpert
493